【问题标题】:Structs are giant. Why?结构是巨大的。为什么?
【发布时间】:2019-06-24 18:32:49
【问题描述】:

我正在抄袭《我的世界》,我正在使用一个结构来存储物品,只是这样:

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;

我对此使用 sizeof,得到 1024 个字节。只是这不应该占用这么多内存。有人可以解释吗?我觉得这非常令人沮丧,我想将它作为数字存储到一个文件中,使用 memcpy 以某种方式将结构转换为 int,但是没有 intager 足够大以容纳大型结构。

【问题讨论】:

  • 看看Item[4][8]。那是该数组中的 32 个元素。从它的元素你得到两个指针,一个双精度和一个整数。你可能会在那里得到一些填充字节。将所有这些乘以 32,您就会得到“巨大”。这都是正常的。
  • @DeiDei 哦让我试试看
  • 除了上面的答案,这样组成结构正常吗?它似乎不可维护且难以推理。为什么不将其分解为易于管理的小单元?
  • @DeiDei 等等。这实际上是有道理的
  • BItem 中的位域毫无意义;在整体类型的每一种情况下,BItemunion-ed 反对更大的东西:TItem 包含两个指针,doubleint

标签: c struct sizeof


【解决方案1】:

这个

            } Item[4][8];

是大小的 32 倍

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

int-pointer 为 8 字节,double 为 8 字节,char 指针为 8 字节,int 为 4 字节,以及一些未知的填充以使对齐正确,可能是 32 字节。所以 4 x 8 x 32 是 1024 字节。

试试这个代码:

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;
}

在一个平台上我得到:

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

所以我们有 4 x 8 字节,即 32 字节。其中一些可能是填充 - 很可能 ID 实际上只是 4 个字节,然后是 4 个字节的填充。

【讨论】:

    猜你喜欢
    • 2019-02-03
    • 2021-05-19
    • 2011-04-04
    • 2014-12-29
    • 1970-01-01
    • 1970-01-01
    • 2021-12-18
    • 2015-09-27
    • 1970-01-01
    相关资源
    最近更新 更多