What is the purpose of the pointers?

Post those lines of code you feel like sharing or find what you require for your project here; or simply use them as tutorials.
Post Reply
Noiecity
Posts: 383
Joined: Wed Aug 23, 2023 7:22 pm
Contact:

What is the purpose of the pointers?

Post by Noiecity »

I have been programming c++ for a short and at the same time long time (short compared to other devs), I love it, but whenever I came across pointers I had a serious problem to understand their usefulness, why use them when I can use static instead?

Until I hit a wall What if I want to create a variable at runtime? Static can only be declared at compile time.... mmm....
Then I understood the truth, and the truth made me free curse, pointers are perfect to create structures and objects dynamically at runtime(with new and delete), it is very similar to declare a non-existent variable at runtime, it is like creating a program inside the program.

Well that's my personal experience, what experience do you have regarding the use of pointers?

...
A useful example of its use, in c++98 (this small program creates .bin files and reads them, it was created taking into account the creation of objects at runtime):

Code: Select all

#include <iostream>
#include <string>
#include <vector>
#include <sstream>
#include <fstream>
#include <cstdlib>
#include <cstring>
#include <limits>
#include <dirent.h>     // For file listing (POSIX systems)

// Fundamental data types
enum DataType {
    BOOL,
    CHAR,
    SIGNED_CHAR,
    UNSIGNED_CHAR,
    SHORT,
    UNSIGNED_SHORT,
    INT,
    UNSIGNED_INT,
    LONG,
    UNSIGNED_LONG,
    FLOAT,
    DOUBLE,
    LONG_DOUBLE,
    STRING
};

// Structure to store inventory data
struct RPGData {
    DataType type;
    std::string label;
    bool has_value;
    union {
        bool bool_val;
        char char_val;
        signed char signed_char_val;
        unsigned char unsigned_char_val;
        short short_val;
        unsigned short unsigned_short_val;
        int int_val;
        unsigned int unsigned_int_val;
        long long_val;
        unsigned long unsigned_long_val;
        float float_val;
        double double_val;
        long double long_double_val;
    };
    std::string string_val; // For string type

    RPGData(DataType t, const std::string &l)
        : type(t), label(l), has_value(false) { }
};

class RPGInventory {
private:
    std::vector<RPGData> items;
    const std::string BIN_DIR;
    
    // Template function for string to T conversion
    template<typename T>
    bool convert(const std::string& str, T& value) {
        std::istringstream iss(str);
        return !(iss >> value).fail();
    }
    
    // Specialization for char
    bool convert(const std::string& str, char& value) {
        if(str.length() == 1) {
            value = str[0];
            return true;
        }
        return false;
    }
    
public:
    RPGInventory() : BIN_DIR("binoutputs/") { }
    
    size_t getItemCount() const {
        return items.size();
    }
    
    bool addItem(const std::string &label, DataType type, const std::string &value) {
        RPGData item(type, label);
        if(!value.empty()){
            bool success = true;
            switch(type) {
                case BOOL:         success = convert(value, item.bool_val); break;
                case CHAR:         success = convert(value, item.char_val); break;
                case SIGNED_CHAR:  success = convert(value, item.signed_char_val); break;
                case UNSIGNED_CHAR:success = convert(value, item.unsigned_char_val); break;
                case SHORT:        success = convert(value, item.short_val); break;
                case UNSIGNED_SHORT: success = convert(value, item.unsigned_short_val); break;
                case INT:          success = convert(value, item.int_val); break;
                case UNSIGNED_INT: success = convert(value, item.unsigned_int_val); break;
                case LONG:         success = convert(value, item.long_val); break;
                case UNSIGNED_LONG: success = convert(value, item.unsigned_long_val); break;
                case FLOAT:        success = convert(value, item.float_val); break;
                case DOUBLE:       success = convert(value, item.double_val); break;
                case LONG_DOUBLE:  success = convert(value, item.long_double_val); break;
                case STRING:       item.string_val = value; break;
                default:           success = false; break;
            }
            if(!success)
                return false;
            item.has_value = true;
        }
        items.push_back(item);
        return true;
    }
    
    bool modifyItem(const std::string &label, const std::string &new_value) {
        for(size_t i = 0; i < items.size(); i++){
            if(items[i].label == label) {
                bool success = true;
                switch(items[i].type) {
                    case BOOL:         success = convert(new_value, items[i].bool_val); break;
                    case CHAR:         success = convert(new_value, items[i].char_val); break;
                    case SIGNED_CHAR:  success = convert(new_value, items[i].signed_char_val); break;
                    case UNSIGNED_CHAR:success = convert(new_value, items[i].unsigned_char_val); break;
                    case SHORT:        success = convert(new_value, items[i].short_val); break;
                    case UNSIGNED_SHORT: success = convert(new_value, items[i].unsigned_short_val); break;
                    case INT:          success = convert(new_value, items[i].int_val); break;
                    case UNSIGNED_INT: success = convert(new_value, items[i].unsigned_int_val); break;
                    case LONG:         success = convert(new_value, items[i].long_val); break;
                    case UNSIGNED_LONG: success = convert(new_value, items[i].unsigned_long_val); break;
                    case FLOAT:        success = convert(new_value, items[i].float_val); break;
                    case DOUBLE:       success = convert(new_value, items[i].double_val); break;
                    case LONG_DOUBLE:  success = convert(new_value, items[i].long_double_val); break;
                    case STRING:       items[i].string_val = new_value; break;
                    default:           success = false; break;
                }
                if(!success)
                    return false;
                items[i].has_value = true;
                return true;
            }
        }
        return false;
    }
    
    void display() const {
        std::cout << "\nInventory:" << std::endl;
        for(size_t i = 0; i < items.size(); ++i) {
            const RPGData &item = items[i];
            std::cout << item.label << " [";
            switch(item.type) {
                case BOOL:          std::cout << "bool"; break;
                case CHAR:          std::cout << "char"; break;
                case SIGNED_CHAR:   std::cout << "signed char"; break;
                case UNSIGNED_CHAR: std::cout << "unsigned char"; break;
                case SHORT:         std::cout << "short"; break;
                case UNSIGNED_SHORT: std::cout << "unsigned short"; break;
                case INT:           std::cout << "int"; break;
                case UNSIGNED_INT:  std::cout << "unsigned int"; break;
                case LONG:          std::cout << "long"; break;
                case UNSIGNED_LONG: std::cout << "unsigned long"; break;
                case FLOAT:         std::cout << "float"; break;
                case DOUBLE:        std::cout << "double"; break;
                case LONG_DOUBLE:   std::cout << "long double"; break;
                case STRING:        std::cout << "string"; break;
            }
            std::cout << "]: ";
            if(!item.has_value)
                std::cout << "NULL";
            else {
                switch(item.type) {
                    case BOOL:          std::cout << (item.bool_val ? "true" : "false"); break;
                    case CHAR:          std::cout << "'" << item.char_val << "'"; break;
                    case SIGNED_CHAR:   std::cout << static_cast<int>(item.signed_char_val); break;
                    case UNSIGNED_CHAR: std::cout << static_cast<unsigned>(item.unsigned_char_val); break;
                    case SHORT:         std::cout << item.short_val; break;
                    case UNSIGNED_SHORT: std::cout << item.unsigned_short_val; break;
                    case INT:           std::cout << item.int_val; break;
                    case UNSIGNED_INT:  std::cout << item.unsigned_int_val; break;
                    case LONG:          std::cout << item.long_val; break;
                    case UNSIGNED_LONG: std::cout << item.unsigned_long_val; break;
                    case FLOAT:         std::cout << item.float_val; break;
                    case DOUBLE:        std::cout << item.double_val; break;
                    case LONG_DOUBLE:   std::cout << item.long_double_val; break;
                    case STRING:        std::cout << "\"" << item.string_val << "\""; break;
                }
            }
            std::cout << std::endl;
        }
    }
    
    std::string getFullFilename(const std::string &filename) const {
        std::string full = filename;
        if(full.size() < 4 || full.substr(full.size()-4) != ".bin") {
            full += ".bin";
        }
        return BIN_DIR + full;
    }
    
    void saveToFile(const std::string &filename) {
        std::string fullFileName = getFullFilename(filename);
        std::ofstream file(fullFileName.c_str(), std::ios::binary);
        if(!file) {
            std::cout << "Error opening file for saving." << std::endl;
            return;
        }
        size_t count = items.size();
        file.write(reinterpret_cast<const char*>(&count), sizeof(size_t));
        for(size_t i = 0; i < items.size(); ++i) {
            const RPGData &item = items[i];
            file.write(reinterpret_cast<const char*>(&item.type), sizeof(DataType));
            size_t label_len = item.label.size();
            file.write(reinterpret_cast<const char*>(&label_len), sizeof(size_t));
            file.write(item.label.c_str(), label_len);
            file.write(reinterpret_cast<const char*>(&item.has_value), sizeof(bool));
            if(item.has_value) {
                if(item.type == STRING) {
                    size_t str_len = item.string_val.size();
                    file.write(reinterpret_cast<const char*>(&str_len), sizeof(size_t));
                    file.write(item.string_val.c_str(), str_len);
                } else {
                    switch(item.type) {
                        case BOOL: file.write(reinterpret_cast<const char*>(&item.bool_val), sizeof(bool)); break;
                        case CHAR: file.write(reinterpret_cast<const char*>(&item.char_val), sizeof(char)); break;
                        case SIGNED_CHAR: file.write(reinterpret_cast<const char*>(&item.signed_char_val), sizeof(signed char)); break;
                        case UNSIGNED_CHAR: file.write(reinterpret_cast<const char*>(&item.unsigned_char_val), sizeof(unsigned char)); break;
                        case SHORT: file.write(reinterpret_cast<const char*>(&item.short_val), sizeof(short)); break;
                        case UNSIGNED_SHORT: file.write(reinterpret_cast<const char*>(&item.unsigned_short_val), sizeof(unsigned short)); break;
                        case INT: file.write(reinterpret_cast<const char*>(&item.int_val), sizeof(int)); break;
                        case UNSIGNED_INT: file.write(reinterpret_cast<const char*>(&item.unsigned_int_val), sizeof(unsigned int)); break;
                        case LONG: file.write(reinterpret_cast<const char*>(&item.long_val), sizeof(long)); break;
                        case UNSIGNED_LONG: file.write(reinterpret_cast<const char*>(&item.unsigned_long_val), sizeof(unsigned long)); break;
                        case FLOAT: file.write(reinterpret_cast<const char*>(&item.float_val), sizeof(float)); break;
                        case DOUBLE: file.write(reinterpret_cast<const char*>(&item.double_val), sizeof(double)); break;
                        case LONG_DOUBLE: file.write(reinterpret_cast<const char*>(&item.long_double_val), sizeof(long double)); break;
                        default: break;
                    }
                }
            }
        }
        std::cout << "Saved " << count << " items to " << fullFileName << std::endl;
    }
    
    void loadFromFile(const std::string &filename) {
        std::string fullFileName = getFullFilename(filename);
        std::ifstream file(fullFileName.c_str(), std::ios::binary);
        if(!file) {
            std::cout << "Error opening file for loading." << std::endl;
            return;
        }
        items.clear();
        size_t count = 0;
        file.read(reinterpret_cast<char*>(&count), sizeof(size_t));
        for(size_t i = 0; i < count; ++i) {
            RPGData item(BOOL, "");
            file.read(reinterpret_cast<char*>(&item.type), sizeof(DataType));
            size_t label_len = 0;
            file.read(reinterpret_cast<char*>(&label_len), sizeof(size_t));
            char *label = new char[label_len + 1];
            file.read(label, label_len);
            label[label_len] = '\0';
            item.label = label;
            delete[] label;
            file.read(reinterpret_cast<char*>(&item.has_value), sizeof(bool));
            if(item.has_value) {
                if(item.type == STRING) {
                    size_t str_len = 0;
                    file.read(reinterpret_cast<char*>(&str_len), sizeof(size_t));
                    char *str = new char[str_len + 1];
                    file.read(str, str_len);
                    str[str_len] = '\0';
                    item.string_val = str;
                    delete[] str;
                } else {
                    switch(item.type) {
                        case BOOL: file.read(reinterpret_cast<char*>(&item.bool_val), sizeof(bool)); break;
                        case CHAR: file.read(reinterpret_cast<char*>(&item.char_val), sizeof(char)); break;
                        case SIGNED_CHAR: file.read(reinterpret_cast<char*>(&item.signed_char_val), sizeof(signed char)); break;
                        case UNSIGNED_CHAR: file.read(reinterpret_cast<char*>(&item.unsigned_char_val), sizeof(unsigned char)); break;
                        case SHORT: file.read(reinterpret_cast<char*>(&item.short_val), sizeof(short)); break;
                        case UNSIGNED_SHORT: file.read(reinterpret_cast<char*>(&item.unsigned_short_val), sizeof(unsigned short)); break;
                        case INT: file.read(reinterpret_cast<char*>(&item.int_val), sizeof(int)); break;
                        case UNSIGNED_INT: file.read(reinterpret_cast<char*>(&item.unsigned_int_val), sizeof(unsigned int)); break;
                        case LONG: file.read(reinterpret_cast<char*>(&item.long_val), sizeof(long)); break;
                        case UNSIGNED_LONG: file.read(reinterpret_cast<char*>(&item.unsigned_long_val), sizeof(unsigned long)); break;
                        case FLOAT: file.read(reinterpret_cast<char*>(&item.float_val), sizeof(float)); break;
                        case DOUBLE: file.read(reinterpret_cast<char*>(&item.double_val), sizeof(double)); break;
                        case LONG_DOUBLE: file.read(reinterpret_cast<char*>(&item.long_double_val), sizeof(long double)); break;
                        default: break;
                    }
                }
            }
            items.push_back(item);
        }
        std::cout << "Loaded " << count << " items from " << fullFileName << std::endl;
    }
    
    void listFiles() const {
        DIR *dir = opendir(BIN_DIR.c_str());
        if(!dir) {
            std::cout << "Could not open directory " << BIN_DIR << std::endl;
            return;
        }
        std::cout << "\nSaved bin files:" << std::endl;
        struct dirent *entry;
        bool found = false;
        while((entry = readdir(dir)) != NULL) {
            std::string fname = entry->d_name;
            if(fname == "." || fname == "..") continue;
            if(fname.size() >= 4 && fname.substr(fname.size()-4) == ".bin") {
                std::cout << " - " << fname << std::endl;
                found = true;
            }
        }
        if(!found) std::cout << " (No saved files)" << std::endl;
        closedir(dir);
    }
};

int main() {
    std::cout << "# Program Start" << std::endl;
    std::cout << "RPG Inventory System" << std::endl;
    std::cout << "Commands:" << std::endl;
    std::cout << "  add <label> <type> [value]" << std::endl;
    std::cout << "  display" << std::endl;
    std::cout << "  save <filename>" << std::endl;
    std::cout << "  load <filename>" << std::endl;
    std::cout << "  list" << std::endl;
    std::cout << "  modify <label> <new_value>" << std::endl;
    std::cout << "  exit" << std::endl << std::endl;
    
    RPGInventory inv;
    std::string command;
    
    while(true) {
        std::cout << "> ";
        std::getline(std::cin, command);
        if(command.empty()) continue;
        
        std::istringstream iss(command);
        std::string action;
        iss >> action;
        
        if(action == "exit") {
            break;
        } else if(action == "add") {
            std::string label, type;
            if(!(iss >> label >> type)) {
                std::cout << "Invalid command!" << std::endl;
                continue;
            }
            DataType dt;
            bool validType = true;
            if(type == "bool") dt = BOOL;
            else if(type == "char") dt = CHAR;
            else if(type == "signed_char") dt = SIGNED_CHAR;
            else if(type == "unsigned_char") dt = UNSIGNED_CHAR;
            else if(type == "short") dt = SHORT;
            else if(type == "unsigned_short") dt = UNSIGNED_SHORT;
            else if(type == "int") dt = INT;
            else if(type == "unsigned_int") dt = UNSIGNED_INT;
            else if(type == "long") dt = LONG;
            else if(type == "unsigned_long") dt = UNSIGNED_LONG;
            else if(type == "float") dt = FLOAT;
            else if(type == "double") dt = DOUBLE;
            else if(type == "long_double") dt = LONG_DOUBLE;
            else if(type == "string") dt = STRING;
            else validType = false;
            
            std::string value;
            std::getline(iss >> std::ws, value);
            if(!validType) {
                std::cout << "Invalid command!" << std::endl;
                continue;
            }
            bool result = inv.addItem(label, dt, value);
            if(!result) std::cout << "Invalid command!" << std::endl;
            else {
                std::cout << "Added " << label;
                if(value.empty()) std::cout << " (NULL)" << std::endl;
                else std::cout << " = " << value << std::endl;
            }
        } else if(action == "display") {
            inv.display();
        } else if(action == "save") {
            std::string filename;
            if(!(iss >> filename)) {
                std::cout << "Invalid command!" << std::endl;
                continue;
            }
            inv.saveToFile(filename);
        } else if(action == "load") {
            std::string filename;
            if(!(iss >> filename)) {
                std::cout << "Invalid command!" << std::endl;
                continue;
            }
            inv.loadFromFile(filename);
        } else if(action == "list") {
            inv.listFiles();
        } else if(action == "modify") {
            std::string label;
            if(!(iss >> label)) {
                std::cout << "Invalid command!" << std::endl;
                continue;
            }
            std::string new_value;
            std::getline(iss >> std::ws, new_value);
            if(new_value.empty()){
                std::cout << "Invalid command!" << std::endl;
                continue;
            }
            bool result = inv.modifyItem(label, new_value);
            if(result) std::cout << "Modified " << label << std::endl;
            else std::cout << "Invalid command!" << std::endl;
        } else {
            std::cout << "Invalid command!" << std::endl;
        }
    }
    return 0;
}
Image
Image
Image

Storing binary values can be useful for storing results at runtime and replicating them as they are loaded into memory and read (considerably reducing the load on the CPU, but increasing the load time at the start of such functionality).

The next example the result resembles loading images into ram memory and playing them back, this could be assigned to events and displayed depending on the relative distance, etc, although for them you have to work with a coordinate system that adapts to that system... that is, precompute using the cache. In PS2 games for example the cache was used to precompute the camera movement:

Code: Select all

#include <windows.h>

#define IMAGE_WIDTH  256
#define IMAGE_HEIGHT 256
#define MAX_FILES    80

struct Pixel {
    int x, y;
    BYTE r, g, b;
};

struct ImageData {
    Pixel pixels[IMAGE_WIDTH * IMAGE_HEIGHT]; // Maximum space for pixels
    int count;
};

// Global variables
ImageData images[MAX_FILES];
HBITMAP bitmaps[MAX_FILES];
int currentFileIndex = 0;
const char* folderPath = "./binoutputs/";
HWND hwnd;

// Function to load a bin file into memory
bool loadBinFile(int index, ImageData& img) {
    char filePath[MAX_PATH];
    wsprintf(filePath, "%s%04d.bin", folderPath, index); // 0001.bin, 0002.bin, etc.

    HANDLE hFile = CreateFile(filePath, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    if (hFile == INVALID_HANDLE_VALUE) return false;

    DWORD bytesRead;
    img.count = 0;

    while (ReadFile(hFile, &img.pixels[img.count].x, sizeof(int), &bytesRead, NULL) && bytesRead > 0 &&
           ReadFile(hFile, &img.pixels[img.count].y, sizeof(int), &bytesRead, NULL) && bytesRead > 0 &&
           ReadFile(hFile, &img.pixels[img.count].r, sizeof(BYTE), &bytesRead, NULL) && bytesRead > 0 &&
           ReadFile(hFile, &img.pixels[img.count].g, sizeof(BYTE), &bytesRead, NULL) && bytesRead > 0 &&
           ReadFile(hFile, &img.pixels[img.count].b, sizeof(BYTE), &bytesRead, NULL) && bytesRead > 0) {
        img.count++;
        if (img.count >= IMAGE_WIDTH * IMAGE_HEIGHT) break;
    }

    CloseHandle(hFile);
    return true;
}

// Function to draw image to bitmap
void drawImageToBitmap(HDC hdc, const ImageData& img) {
    for (int i = 0; i < img.count; i++) {
        SetPixel(hdc, img.pixels[i].x, img.pixels[i].y, RGB(img.pixels[i].r, img.pixels[i].g, img.pixels[i].b));
    }
}

// Function to create bitmap from image data
HBITMAP createBitmapFromImage(const ImageData& img) {
    HDC hdcScreen = GetDC(NULL);
    HDC hdcMem = CreateCompatibleDC(hdcScreen);
    HBITMAP hbm = CreateCompatibleBitmap(hdcScreen, IMAGE_WIDTH, IMAGE_HEIGHT);
    HBITMAP hbmOld = (HBITMAP)SelectObject(hdcMem, hbm);

    // Initialize bitmap with black background
    HBRUSH hbrBackground = CreateSolidBrush(RGB(0, 0, 0)); // Black background
    RECT rect = { 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT };
    FillRect(hdcMem, &rect, hbrBackground);
    DeleteObject(hbrBackground);

    drawImageToBitmap(hdcMem, img);

    SelectObject(hdcMem, hbmOld);
    DeleteDC(hdcMem);
    ReleaseDC(NULL, hdcScreen);

    return hbm;
}

// Window procedure
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
    static int windowWidth = IMAGE_WIDTH;
    static int windowHeight = IMAGE_HEIGHT;
    static int bitmapWidth = IMAGE_WIDTH;
    static int bitmapHeight = IMAGE_HEIGHT;

    switch (msg) {
        case WM_PAINT: {
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint(hwnd, &ps);
            HDC hdcMem = CreateCompatibleDC(hdc);
            HBITMAP hbmOld = (HBITMAP)SelectObject(hdcMem, bitmaps[currentFileIndex]);

            // Calculate scaled bitmap size maintaining aspect ratio
            int scaledWidth = windowWidth;
            int scaledHeight = windowHeight;
            if (windowWidth > windowHeight) {
                scaledWidth = windowHeight;
                scaledHeight = windowHeight;
            } else {
                scaledWidth = windowWidth;
                scaledHeight = windowWidth;
            }

            // Calculate position to center the bitmap
            int xPos = (windowWidth - scaledWidth) / 2;
            int yPos = (windowHeight - scaledHeight) / 2;

            // Draw scaled bitmap
            StretchBlt(hdc, xPos, yPos, scaledWidth, scaledHeight, hdcMem, 0, 0, bitmapWidth, bitmapHeight, SRCCOPY);

            SelectObject(hdcMem, hbmOld);
            DeleteDC(hdcMem);
            EndPaint(hwnd, &ps);
        } break;

        case WM_SIZE: {
            windowWidth = LOWORD(lParam);
            windowHeight = HIWORD(lParam);
            InvalidateRect(hwnd, NULL, TRUE);
        } break;

        case WM_DESTROY:
            PostQuitMessage(0);
            break;

        default:
            return DefWindowProc(hwnd, msg, wParam, lParam);
    }
    return 0;
}

// Main WinMain function
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
    WNDCLASS wc = { 0 };
    wc.lpfnWndProc = WndProc;
    wc.hInstance = hInstance;
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wc.lpszClassName = "ImageViewer";

    RegisterClass(&wc);
    hwnd = CreateWindow("ImageViewer", "BIN Image Viewer", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, IMAGE_WIDTH, IMAGE_HEIGHT, NULL, NULL, hInstance, NULL);
    ShowWindow(hwnd, nCmdShow);

    // Load all bin files into RAM and create bitmaps
    for (int i = 1; i <= MAX_FILES; i++) {
        if (!loadBinFile(i, images[i - 1])) {
            break;
        }
        bitmaps[i - 1] = createBitmapFromImage(images[i - 1]);
    }

    // Main loop to cycle images with 16 ms delay
    while (true) {
        currentFileIndex = (currentFileIndex + 1) % MAX_FILES;
        InvalidateRect(hwnd, NULL, FALSE); // Use FALSE to prevent background erase
        UpdateWindow(hwnd);
        Sleep(16);

        MSG msg;
        while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
            if (msg.message == WM_QUIT) {
                return msg.wParam;
            }
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }

    return 0;
}
The result:
Image

(if you try this animation, you can pause the animation by clicking on the title of the window)

Binary files used:
https://drive.google.com/file/d/1wsQgdx ... sp=sharing


We're talking about my cpu staying at 0% usage... obviously there was cpu usage but it was very low. When using GDI I was using 1% of my graphics card, watching videos in 240p consumes me more(4-5%).
Last edited by Noiecity on Wed Feb 26, 2025 2:05 pm, edited 1 time in total.
Irrlicht is love, Irrlicht is life, long live to Irrlicht
CuteAlien
Admin
Posts: 10021
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: What is the purpose of the pointers?

Post by CuteAlien »

Yeah, dynamically allocating objects (in heap memory) is one reason where you need pointers. Because the compiler _can't_ know the addresses of those objects earlier. It only knows the address where it is in memory after the operating system tells them at runtime.

Other things where they are useful:

- Via pointer the same object can be shared by several others objects. If you would work with object copies instead of addresses to the original object then you a) spend several times more memory (one more time per copy) and b) have to ensure yourself all copies stay indentical over lifetime.

- It is in most cases faster to pass around an address than it is to copy around a full object. Each pointer on a modern PC is 64-bit long, so as soon as your object is larger than 64-bit then there is simply more bytes to copy. Thought pointers come alsoe with a speed down-side: Using variables in an object through a pointer is a bit slower. First it adds an indirection - it has to read the address of the real object first. But even worse is that they can mess with processor caching (the real object is usually not in the same cache as it's pointer, so the cache becomes invalid). Still in most cases it's worth it.
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
n00bc0de
Posts: 133
Joined: Tue Oct 04, 2022 1:21 am

Re: What is the purpose of the pointers?

Post by n00bc0de »

Pointers are also needed in low level programming. On older systems, you would use a pointer to point to video memory for drawing or reading a point in memory to get hardware signals. You will likely be using an API for this on modern systems but there is still a use for understanding this if you are dealing with a frame buffer.
Noiecity
Posts: 383
Joined: Wed Aug 23, 2023 7:22 pm
Contact:

Re: What is the purpose of the pointers?

Post by Noiecity »

Thank you for your information, this is sometimes difficult information to learn without experience :-D
Irrlicht is love, Irrlicht is life, long live to Irrlicht
Post Reply