C / C ++中结构的字段对齐

结构的成员是用C / C ++打包的吗? (通过打包我的意思是它们是紧凑的,在字段之间没有内存空间)

这不是对齐的意思,不,没有保证特定的对齐或包装。 元素将按顺序排列,但编译器可以在其选择的位置插入填充。 这实际上创建 (有用)对齐。 例如,对于x86:

 struct s { char c; int i; }; 

c和i之间可能(但不一定)是三个字节。 这允许i在字边界上对齐,这可以提供更快的存储器访问(在某些体系结构上,它是必需的)。

从C99§6.7.2.1开始:

结构或联合对象的每个非位字段成员以适合其类型的实现定义方式对齐。

您要求的是包装 ,对齐是不同的。 两者都超出了语言的范围,并且特定于每个实现。 看看这里 。

一般不是。 这里有一些信息。

根据编译器的不同,您可以引入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 */ 

通常 (但不保证),结构的成员是字对齐的。 这意味着将填充小于单词大小的字段以占用整个单词。

但是,当结构的下一个成员可以放在同一个单词中时,编译器会将两个成员放在同一个单词中。 这在空间方面更有效,但根据您的平台,检索所述成员可能在计算上更昂贵。

在Cygwin下使用GCC的32位系统上,这个程序……

 #include  struct foo { char a; int b; char c; }; int main(int argc, char** argv) { std::cout << sizeof(foo) << std::endl; } 

输出'12',因为两个字符都是字对齐的,每个字符占用4个字节。

但是,将结构切换为

 struct foo { char a; char c; int b; }; 

输出为'8',因为彼此相邻的两个字符可以放在一个单词中。

可以打包字节以节省内存。 例如,pack(2)将告诉成员长度超过一个字节以打包到两个字节,以便保持两个字节的边界,以便任何填充成员都是两个字节长。 有时,打包被用作标准通信协议的一部分,它需要一定的大小。 以下是维基百科关于C / C ++和填充的说法:

仅当结构成员后跟具有较大对齐要求的成员或在结构的末尾时才插入填充。 通过更改结构中成员的顺序,可以更改维持对齐所需的填充量。 例如,如果成员按升序或降序排列要求排序,则需要最少量的填充。 所需的最小填充量总是小于结构中的最大对齐。 计算所需的最大填充量更复杂,但总是小于所有成员的对齐要求之和减去最少对齐的一半结构成员的对齐要求总和的两倍。

虽然C和C ++不允许编译器重新排序结构成员以节省空间,但其他语言可能会。

因为在struct中,编译器将事物视为单词,所以如果依赖于结构的大小为某个大小,有时必须小心。 例如,对齐char与int。

它们默认不打包,而是根据机器的设置方式对齐。 如果你确实想要它们被打包。 然后你可以在结构声明的末尾使用__attribute__((__packed__)) ,如下所示:

 struct abc { char a; int b; char c; }__attribute__((__packed__)); 

然后,为

 struct abc _abc; 

_abc将被打包。

参考: http : //www.grok2.com/structure_packing.html

看到相同结构变化的某些输出可能会给出正在发生的事情的线索。 读完之后,如果我没有弄错,小类型将被填充为单词长度。

 struct Foo { char x ; // 1 byte int y ; // 4 byte char z ; // 1 byte int w ; // 4 byte }; struct FooOrdered { char x ; // 1 byte char z ; // 1 byte int y ; // 4 byte int w ; // 4 byte }; struct Bar { char x ; // 1 byte int w ; // 4 byte }; struct BarSingleType { char x ; // 1 byte }; int main(int argc, char const *argv[]) { cout << sizeof(Foo) << endl; cout << sizeof(FooOrdered) << endl; cout << sizeof(Bar) << endl; cout << sizeof(BarSingleType) << endl; return 0; } 

在我的环境中输出是这样的:

 16 12 8 1