语言是C与gcc编译器
如果我制作这样的结构
struct test {
char item_1[2];
char item_3[4];
char item_4[2];
char item_5[2];
char item_6[4];
};
我做了一个sizeof(struct test)它返回14(字节)。这是预期的结果。
但如果我这样做
struct test {
int16_t item_1;
int32_t item_3;
int16_t item_4;
int16_t item_5;
int32_t item_6;
};
sizeof(struct test)会返回一些奇怪的东西,比如44.当我使用gnu ddd进行调试时,我可以看到结构内部,看到它看起来都正常,所有项目都有预期的字节数。
那么为什么sizeof运算符会返回一个意外的值呢?
答案 0 :(得分:3)
你混合了32/16位整数。
int16_t item_1[2]; // 2 * 2 = 4
int32_t item_3[4]; // 4 * 4 = 16
int16_t item_4[2]; // 2 * 2 = 4
int16_t item_5[2]; // 2 * 2 = 4
int32_t item_6[4]; // 4 * 4 = 16
// sum = 44
答案 1 :(得分:1)
编译器可以在struct成员之间或最后一个成员之后插入填充。通常这样做是为了满足对准要求。例如,int32_t
对象可能需要4字节对齐,因此编译器在第一个和第二个成员之间插入2个字节的填充。具体细节因平台而异。
答案 2 :(得分:1)
编译器需要在结构成员之间插入填充以在其类型的边界上对齐每个成员,并按结构对成员的成员进行排序。如果对它们重新排序,使得最大的成员位于结构定义的开头,则它们的大小将相同。但是既然你正在尝试使用char数组,我猜你没有结构的原始定义,并且你试图访问一些外部定义和创建的对象的字段。在这种情况下,我建议您获取正确的标题或使用char []版本并将char *转换为它实际的任何类型。
答案 3 :(得分:1)
对齐问题是因为现代32位CPU在32位地址边界上以32位字大小工作。如果32位边界上的32位字包含2个16位值,则会导致需要额外的指令才能获得正确的16位(即屏蔽和移位,以便保留正确的16位) 。如果32位字在32位边界上被分割,那么还有更多的工作要做。检索它。
默认情况下,权衡是拥有更快的程序,而不是尽可能高效地使用内存。如果在使用结构构件的任何地方都需要额外的几条指令,那么这可能会使用更多的内存,而不是更紧密的包装结构保存,所以一开始并不明显,这是正确的选择。
如果您需要有效地存储结构(以性能为代价),那么“#pragma pack”允许您更紧密地打包成员,但它会导致更慢的程序。
http://gcc.gnu.org/onlinedocs/gcc/Structure_002dPacking-Pragmas.html
答案 4 :(得分:0)
struct test {
int16_t item_1[2]; // 2 * 16 +
int32_t item_3[4]; // 4 * 32 +
int16_t item_4[2]; // 2 * 16 +
int16_t item_5[2]; // 2 * 16 +
int32_t item_6[4]; // 4 * 32
// total = 352
};
352位除以8(8位进入一个字节)是44个字节。