struct的大小和相应的变量

如果我定义一个char变量

char a; 

以及具有单个char成员的结构

 struct OneChar { char a; }; 

这两个定义在所有编译器中的大小都是’char’吗? 我的疑问是,如果我们在结构中定义一个char变量,由于内存打包它会比char的大小更大吗?

这取决于架构和编译器。 对于这种特殊情况,您应该是安全的,但请查看数据结构填充 。

这是一段摘录 :

x86上C结构的典型对齐方式

数据结构成员按顺序存储在内存中,因此在下面的结构中,成员Data1将始终位于Data2之前,而Data2将始终位于Data3之前:

 struct MyData { short Data1; short Data2; short Data3; }; 

如果类型“short”存储在两个字节的存储器中,那么上面描述的数据结构的每个成员将是2字节对齐的。 Data1将位于偏移0,Data2位于偏移2处,Data3位于偏移4.此结构的大小为6个字节。

结构的每个成员的类型通常具有默认对齐,这意味着除非程序员另外请求,否则它将在预定边界上对齐。 在编译32位x86时,以下典型的对齐对Microsoft,Borland和GNU的编译器有效:

  • char(一个字节)将是1字节对齐的。
  • 短(两个字节)将是2字节对齐的。
  • int(四个字节)将是4字节对齐的。
  • 浮点数(四个字节)将是4字节对齐的。
  • 双(八字节)将在Windows上对齐8字节,在Linux上对齐4字节。

这是一个包含各种类型成员的结构,在编译之前总共有8个字节:

 struct MixedData { char Data1; short Data2; int Data3; char Data4; }; 

编译后,数据结构将补充填充字节,以确保每个成员的正确对齐:

 struct MixedData /* after compilation */ { char Data1; char Padding0[1]; /* For the following 'short' to be aligned on a 2 byte boundary */ short Data2; int Data3; char Data4; char Padding1[3]; }; 

结构的编译大小现在是12个字节。 重要的是要注意,最后一个成员填充了符合最大类型结构所需的字节数。 在这种情况下,将3个字节添加到最后一个成员,以将结构填充为长字的大小。

通过更改编译器对结构成员的对齐(或“打包”),可以更改结构的对齐以减少它们所需的内存(或符合现有格式)。

请求上面的MixedData结构与一个字节边界对齐将使编译器丢弃成员的预定对齐,并且不插入填充字节。

虽然没有标准的方法来定义结构成员的对齐,但是一些编译器使用#pragma指令来指定源文件中的包装。 这是一个例子:

 #pragma pack(push) /* push current alignment to stack */ #pragma pack(1) /* set alignment to 1 byte boundary */ struct MyPackedData { char Data1; long Data2; char Data3; }; #pragma pack(pop) /* restore original alignment from stack */ 

该结构的编译大小为6个字节。 上述指令可在Microsoft,Borland,GNU和许多其他编译器中获得。

只要有一个成员,我认为你的假设是安全的。

您列出的案例将在我知道的所有ABI下打包为1字节结构。

但是如果你需要可移植地处理更复杂的情况,最佳做法是在计算内存大小时始终使用sizeof(struct OneChar) ,并在需要通过以下方法计算地址时获取字段地址的偏移量:

 (char*)&(((struct OneChar*)0)->a) - (char*)0 

所有s都具有相同的大小,无论它们是独立的还是在结构内。

结构内部可能发生的是成员之间存在填充……但这也可能发生在“独立”变量中。

获取结构的大小时,它包含填充字节。 但是,如果您有类似以下内容:

 void fun() { char c; int n; } 

无论出于什么原因,编译器都可以自由插入填充。 因此,在独立变量的情况下,填充可能存在,你只是在结构的情况下无法知道。

各种编译器将优化以在结构之间或结尾处添加填充。 因此,在所有编译器或平台上假设分配的大小看起来并不安全。 检查编译器选项以设置struct padding。

例如,Visual Studio使用#pragma pack指令覆盖默认优化。