Search code examples
cstructsizeof

Structs are giant. Why?


I am making a ripoff of minecraft and I am using a struct to store items, and just this:

typedef struct Item {
    union {
        struct {
            int V:4;
            int Q:6;
            int ID;
        } BItem;
        struct {
            union {
                struct {
                    int V:4;
                    int Q:6;
                    int ID;
                } BItem;
                struct {
                    int *Ench;
                    double Durability;
                    char *Name;
                    int ID;
                } TItem;
            } Item[4][8];
            enum {
                ICBItem,
                ICTItem
            } Type;
        } CItem;
        struct {
            int *Ench;
            double Durability;
            char *Name;
            int ID;
        } TItem;
    } ItemUnion;
    enum {
        BItem,
        CTtem,
        TItem
    } Type;
    void *UseHandler;
} Item;

I use sizeof on this and I get 1024 bytes. Just this should not take up so much memory. Can someone explain? I find this very frustrating and I want to store this into a file as a number using somehow casting the struct into an int using memcpy, but NO intager is big enough for a massive struct.


Solution

  • This

                } Item[4][8];
    

    is 32 times the sizeof

                struct {
                    int *Ench;
                    double Durability;
                    char *Name;
                    int ID;
    

    With int-pointer at 8 bytes and and double at 8 bytes and char pointer at 8 bytes and int at 4 bytes and some unknown padding to get the alignment correct, that may be 32 bytes. So 4 x 8 x 32 is 1024 bytes.

    Try this code:

    int main()
    {
        Item x;
        printf("%zu\n", sizeof x);
        printf("%zu\n", sizeof x.ItemUnion.CItem);
        printf("%zu\n", sizeof x.ItemUnion.CItem.Item);
        printf("%zu\n", sizeof x.ItemUnion.CItem.Item[0][0]);
        printf("%zu\n", sizeof x.ItemUnion.CItem.Item[0][0].TItem);
    
        printf("%p\n", (void*)&x.ItemUnion.CItem.Item[0][0].TItem.Ench);
        printf("%p\n", (void*)&x.ItemUnion.CItem.Item[0][0].TItem.Durability);
        printf("%p\n", (void*)&x.ItemUnion.CItem.Item[0][0].TItem.Name);
        printf("%p\n", (void*)&x.ItemUnion.CItem.Item[0][0].TItem.ID);
        printf("%p\n", (void*)&x.ItemUnion.CItem.Item[0][1].TItem.Ench);
        return 0;
    }
    

    On one plat form I get:

    1048
    1032
    1024
    32
    32
    0x7ffcdec7ea90  // Ench
    0x7ffcdec7ea98  // Durability - 8 bytes later so Ench takes 8 bytes
    0x7ffcdec7eaa0  // Name - 8 bytes later so Durability takes 8 bytes
    0x7ffcdec7eaa8  // ID - 8 bytes later so Name takes 8 bytes
    0x7ffcdec7eab0  // Ench of next element - 8 bytes later so ID takes 8 bytes
    

    So we have 4 x 8 bytes which is 32 bytes. Some of these may be padding - most likely ID is really just 4 bytes followed by 4 bytes padding.