为什么struct的大小不等于其各个成员类型的大小总和?

时间:2010-07-29 20:15:56

标签: c visual-c++ compiler-construction

  

可能重复:
  Why isn’t sizeof for a struct equal to the sum of sizeof of each member?

我想之前必须提出类似(重复)的问题。但是我找不到它们。基本上我不知道要搜索什么。所以在这里问一下。

为什么struct的大小不等于其各个成员类型的大小总和? 我正在使用visual C ++编译器。

例如,假设32位机器。 {=> sizeof(int)== 4; sizeof(char)== 1; sizeof(短)== 2; }

  struct {
      int k;
      char c;
  } s;

预期的大小是4 + 1 = 5;但sizeof(s)给出8.这里char占用4个字节而不是1.我不知道确切原因,但我的猜测是编译器这样做是为了提高效率。

struct{
 long long k;
 int i;
} s;

预期大小为4 + 4 = 8(在32位机器上)和8 + 4 = 12(在64位机器上)。但奇怪的是,sizeof(s)给出了16.这里有int& long long每个占用8个字节。

  1. 这叫什么东西?
  2. 究竟发生了什么?
  3. 为什么编译器会这样做?
  4. 有没有办法告诉编译器停止这样做?

3 个答案:

答案 0 :(得分:6)

这是因为编译器使用填充将每个元素转换为特定于您要编译的体系结构的字对齐。

这可能是出于以下几个原因之一,但通常是:

  1. 因为某些CPU在不在其自身大小的地址倍数时,根本无法读取长或长多字节值。

  2. 因为可以读取非对齐数据的CPU可能比对齐的速度慢得多。

  3. 您通常可以使用特定于编译器的指令或编译指示来强行关闭它。

    执行此操作时,编译器将生成相对低效的代码,以使用多个读/写操作访问非对齐数据。

答案 1 :(得分:3)

这称为 padding ;这包括添加一些更多的字节,以便在可被某些特殊数字整除的地址上对齐结构,通常为2,4或8.编译器甚至可以在成员之间放置填充以在这些边界上对齐字段。

这是一种性能优化:访问对齐的内存地址更快,有些架构甚至不支持访问未对齐的地址。

对于VC ++,您可以使用pack pragma来控制字段之间的填充。但请注意,不同的编译器有不同的处理方式,因此,例如,如果您还想支持GCC,则必须使用不同的声明。

答案 2 :(得分:0)

编译器可以在成员之间或结构的末尾插入填充。通常在成员之间进行填充以使成员保持对齐以最大化访问速度。如果你决定创建一个结构数组,最后的填充是基于相同的原因完成的。

为了防止它发生,请使用#pragma pack(1)之类的内容。