C++ 结构的大小是否必须是该结构对齐的精确倍数?
我再一次质疑一个长期存在的信念 直到今天,我相信下面结构的对齐通常是4,大小通常是5C++ 结构的大小是否必须是该结构对齐的精确倍数?,c++,struct,alignment,sizeof,C++,Struct,Alignment,Sizeof,我再一次质疑一个长期存在的信念 直到今天,我相信下面结构的对齐通常是4,大小通常是5 struct example { int m_Assume_32_Bits; char m_Assume_8_Bit_Bytes; }; 由于这个假设,我有一个数据结构代码,它使用offsetof来确定数组中两个相邻项之间的字节距离。今天,我发现一些旧代码正在使用sizeof,但它不应该使用,我不明白为什么我没有从中得到bug,我编写了一个单元测试——测试通过了,这让我很惊讶 一点调查表明,我用
struct example
{
int m_Assume_32_Bits;
char m_Assume_8_Bit_Bytes;
};
由于这个假设,我有一个数据结构代码,它使用offsetof来确定数组中两个相邻项之间的字节距离。今天,我发现一些旧代码正在使用sizeof,但它不应该使用,我不明白为什么我没有从中得到bug,我编写了一个单元测试——测试通过了,这让我很惊讶
一点调查表明,我用于测试的类型(类似于上面的结构)的大小是对齐的精确倍数,即8字节。它在最后一个成员之后有填充物。这是一个例子,为什么我从来没有想到这一点
struct example2
{
example m_Example;
char m_Why_Cant_This_Be_At_Offset_6_Bytes;
};
谷歌搜索显示了一些例子,这些例子清楚地表明,允许在最后一个成员之后进行填充,例如“或在结构末尾”位
这有点尴尬,因为我最近发布了这条评论(我对这个答案的第一条评论)
我无法确定的是这个填充的精确倍数是否由C++标准保证,或者它是否只是被允许的东西和一些(但不是全部)编译器所做的。
那么,结构的大小是否需要是根据C++标准的结构的对齐的精确倍数?
<如果C标准有不同的保证,我也感兴趣,但是重点是C++。< /P> < P>一个对齐尺寸定义: 结构的对齐大小是当您拥有该结构的数组时,从一个元素到下一个元素的偏移量从本质上讲,如果有一个包含两个元素的结构数组,那么这两个元素都需要有对齐的成员,这意味着是的,大小必须是对齐的倍数。(我不确定是否有任何标准明确实施了这一点,但由于结构的大小和对齐方式不取决于结构是单独的还是在数组中,因此相同的规则适用于这两种情况,因此它实际上不可能是任何其他方式。)该标准很少涉及填充和对齐。保证很少。唯一可以打赌的是,第一个元素位于结构的开头。然后…对齐和填充可以是任何内容。因此,将问题分成两部分: 1。这合法吗? [5.3.3.2]当应用于一个类时,[sizeof()运算符]的结果是该类对象中的字节数,包括将该类型的对象放入数组所需的任何填充 所以,不,不是 2。那么,为什么不是呢? 在这里,我只是猜测 2.1。指针算法变得更加奇怪
如果对齐是“在阵列元素之间”,但不会影响大小,则Zthings将变得不必要的复杂,例如
(char *)(X+1) != ((char *)X) + sizeof(X)
(我有一种预感,即使没有上述声明,这也是标准隐含的要求,但我无法证明)
2.2简单性如果对齐影响大小,则可以通过查看单个类型来确定对齐和大小。考虑这一点:
struct A { int x; char y; }
struct B { A left, right; }
根据当前的标准,我只需要知道sizeof(A)就可以确定B的大小和布局。根据您的建议,我需要知道A的内部结构,类似于您的代码> ExpReule2:对于一个“更好的打包”,SigeOf(示例)是不够的,您需要考虑示例的内部结构。p> 我不确定这是否在实际的C/C++标准中,我倾向于说这取决于编译器(为了安全起见)。然而,几个月前,我有一段“有趣”的时间来弄清楚这一点,当时我必须作为协议的一部分,通过网络发送动态生成的C结构作为字节数组,以便与芯片通信。所有结构的对齐方式和大小必须与芯片上运行的代码中的结构保持一致,该代码是使用用于MIPS架构的GCC变体编译的。我将尝试给出算法,它应该适用于gcc的所有变体(希望也适用于大多数其他编译器) 所有基本类型,如char、short和int都与它们的大小对齐,并且它们与下一个可用位置对齐,而与父对象的对齐方式无关。为了回答最初的问题,是的,总尺寸是路线的倍数
// size 8
struct {
char A; //byte 0
char B; //byte 1
int C; //byte 4
};
即使结构的对齐是4个字节,字符仍然被尽可能地压缩
结构的对齐方式等于其成员的最大对齐方式
例如:
//size 4, but alignment is 2!
struct foo {
char A; //byte 0
char B; //byte 1
short C; //byte 3
}
//size 6
struct bar {
char A; //byte 0
struct foo B; //byte 2
}
这也适用于工会,而且奇怪的是。仅由于对齐,活接头的尺寸可以大于其构件的任何尺寸:
//size 3, alignment 1
struct foo {
char A; //byte 0
char B; //byte 1
char C; //byte 2
};
//size 2, alignment 2
struct bar {
short A; //byte 0
};
//size 4! alignment 2
union foobar {
struct foo A;
struct bar B;
}
使用这些简单的规则,您应该能够计算出遇到的任何可怕的嵌套联合/结构的对齐方式/大小。这都是出于记忆,所以如果我错过了一个角落的情况,不能从这些规则决定,请让我知道 似乎C++03标准没有说明(或者我没有发现)对齐填充字节是否应该包含在对象表示中 C99标准说结构类型或联合类型的“sizeof”包括内部填充和尾部填充,但我不确定是否所有对齐填充都包含在“尾部填充”中 现在回到你的例子。真的没有混乱
sizeof(示例)==8
意味着该结构需要8个字节来表示自身,包括尾随的3个填充字节。如果第二个结构中的字符偏移量为6,它将覆盖m_Example
使用的空间。特定类型的布局由实现定义,并且在整个实现中应保持稳定
尽管如此,p+1
是否等于
9.3.0
sizeof(WeirdType) = 3
alignof(WeirdType) = 4
9.0.1
sizeof(WeirdType) = 3
alignof(WeirdType) = 4