【问题标题】:Sizeof operator returns incorrect size? [duplicate]Sizeof 运算符返回不正确的大小? [复制]
【发布时间】:2011-12-01 20:08:43
【问题描述】:

可能重复:
Why isn't sizeof for a struct equal to the sum of sizeof of each member?
Extra bytes when declaring a member of a struct as uint32_t

由于某种原因,sizeof 运算符为此结构返回了一个虚假的大小(48 而不是40):

typedef struct mbdb_file_info {
  uint16_t mode;

  uint32_t unk0;
  uint32_t unk1;
  uint32_t user_id;
  uint32_t group_id;

  uint32_t time0;
  uint32_t time1;
  uint32_t time2;

  uint64_t length;
  uint8_t flag;
  uint8_t property_count;
} mbdb_file_info;

所以这里是一个简单的测试:

printf("%ld %ld %ld %ld: %ld", sizeof(uint8_t),
                                sizeof(uint16_t), 
                                sizeof(uint32_t),
                                sizeof(uint64_t),
                                sizeof(mbdb_file_info));

哪些打印:

1 2 4 8: 48

这是怎么发生的?如果将所有尺寸加在一起,您会得到40,而不是4848到底是从哪里来的?

如果这是一些奇怪的x86-64 perk,我如何确保结构的所有字段占据我希望它们占据的数量(我正在向这个结构投射一堆字节)?

【问题讨论】:

    标签: c struct x86-64 structure-packing


    【解决方案1】:

    编译器可能会在结构的中间附加一些字节以对齐结构成员。 struct的大小至少是他成员大小的总和,但不限于此。

    【讨论】:

    • 哦,所以我需要volatile struct
    • 您需要添加__attribute__((packed))
    • @Nick 请注意,使用packed 可能会影响程序的性能。未对齐的内存访问可能比对齐的访问更昂贵,并且可以在循环中产生可衡量的差异。
    【解决方案2】:

    您还可以通过重新排序结构成员来摆脱填充。例如,如果您声明 64 位,然后是 32 位,然后是 16 位,然后是 8 位,它将自然对齐,并且没有额外的填充字节。

    【讨论】:

      【解决方案3】:

      由于结构填充(不确定这里的术语是什么)。最大的字段是 64 位,所以一切都按照它对齐。所以,我们有:

      typedef struct mbdb_file_info {
        uint16_t mode; // 16 + 
      
        uint32_t unk0; // 32 = 48, so add 16 more to align to 64bit;
        uint32_t unk1; // this
        uint32_t user_id; // and this give 64bits ;
        uint32_t group_id; // again this
      
        uint32_t time0; // plus this - 64bits;
        uint32_t time1; // this 
        uint32_t time2; // and this = 64bit ;
      
        uint64_t length; // this is 64 by itself
        uint8_t flag;  // this
        uint8_t property_count; // +this is 16, add 48 for the alignment
      } mbdb_file_info; // when you sum all bits (+ the additional for padding)
                            // you have exactly 48B
      

      【讨论】:

        【解决方案4】:

        对齐。某些数据类型在某些边界处对齐(读取:地址可被 2 整除,例如 16),具体取决于架构,这会导致结构中的填充。

        有一些编译器选项可以抑制这种行为,and the gcc documentation tells you how to use the aligned attribute 就可以了。

        【讨论】:

          【解决方案5】:

          这称为对齐结构填充

          可能发生的情况是 8 位和 16 位值被填充到 32 位,并且整个结构被填充为机器字长 (8) 的倍数。

          【讨论】:

            猜你喜欢
            • 2014-10-02
            • 2012-05-29
            • 1970-01-01
            • 2021-04-03
            • 1970-01-01
            • 2013-11-08
            • 2012-10-16
            • 1970-01-01
            • 2023-04-08
            相关资源
            最近更新 更多