视觉C++中的结构对齐
Structure alignment in Visual C++
Visual C++同时提供了一个编译器开关(/Zp
)和pack
杂注来影响结构成员的排列。但是,我似乎对它们的工作方式有一些误解。
根据 MSDN,对于给定的对齐值 n,
成员的对齐方式将位于边界上,该边界为 n 的倍数或成员大小的倍数,以 较小。
假设包值为 8 字节(这是默认值)。在结构中,我认为任何大小小于 8 字节的成员都将处于其自身大小的倍数的偏移量。大小为 8 字节或更大的任何成员的偏移量均为 8 字节的倍数。
现在采用以下程序:
#include <tchar.h>
#pragma pack(8)
struct Foo {
int i1;
int i2;
char c;
};
struct Bar {
char c;
Foo foo;
};
int _tmain(int argc, _TCHAR* argv[]) {
int fooSize = sizeof(Foo); // yields 12
Bar bar;
int fooOffset = ((int) &bar.foo) - ((int) &bar); // yields 4
return 0;
}
Foo
结构的大小为 12 字节。所以在 Bar
内,我希望Foo
成员位于偏移量 8(8 的倍数),而实际上它在偏移量 4。为什么?
此外,Foo
实际上只有 4+4+1 = 9 字节的数据。编译器会自动在末尾添加填充字节。但同样,给定 8 个字节的对齐值,它不应该填充到 8 的倍数而不是 4 吗?
任何澄清表示赞赏!
你的摘录解释了这一点,"以较小的为准"。在 32 位平台上,int
为 4 个字节。4 小于 8。所以它有一个 4 字节对齐。
pack
杂注会导致东西被打包,而不是拆包。除非有理由,否则它不会填充。
请记住为什么对齐首先很重要。 它允许CPU快速读取内存,而无需多路复用字节。 cpu 从不一口气读取结构,它只访问其成员。 因此,Foo结构体为12字节这一事实无关紧要。 只有其成员的一致性才重要。 鉴于没有 Foo 成员的对齐要求大于 4,Bar.foo 成员只需要对齐到 4。
Foo 是 12 字节而不是 9 字节也可以使用解释。 编译器在末尾添加 3 个字节的填充,以便 Foo 数组仍然为每个数组元素正确对齐成员。
正如您的报价所说 - 要测试 8 字节对齐方式,您需要 8 种或更多字节数据类型。下面是一些显式大小类型的示例。此外,将小元素放在末尾不会显示填充,因为它可以从结构的末尾删除。
#include <stdio.h>
int
main(int argc, char *argv[])
{
struct S {
__int64 a;
__int8 b;
__int64 c;
};
#pragma pack(push,1)
struct T {
__int64 a;
__int8 b;
__int64 c;
};
#pragma pack(pop)
#pragma pack(push,8)
struct U {
__int64 a;
__int8 b;
__int64 c;
};
struct B {
__int8 c;
struct U s;
};
#pragma pack(pop)
printf("S %d T %d U %d B %dn",
sizeof(struct S), sizeof(struct T),
sizeof(struct U), sizeof(struct B));
return 0;
}
使用 VC 2010 编译此内容:
C:src>cl -nologo -W3 -Od packing.c && packing.exe
packing.c
S 24 T 17 U 24 B 32
- OPENCL结构对齐错误
- 数据结构对齐:为什么Char和STD :: String的数组不同
- interpret_cast和结构对齐
- 结构对齐填充、最大填充大小和结构成员顺序
- 与此类结构对齐是否以C 标准为标准
- 64位Windows API结构对齐导致命名管道上出现“拒绝访问”错误
- 如何检测/查找 64 位结构对齐问题
- 检索数据结构对齐信息
- C# 中的结构对齐
- 视觉C++中的结构对齐
- 为什么iOS中的结构对齐方式不同
- 内存对齐-结构的总大小是结构对齐的倍数,而不是处理大小
- 内存对齐到结构-对齐大小等于最大成员大小
- 结构对齐 C/C++
- C与C++结构对齐
- 警告 C4121 行为和结构对齐 (Visual Studio 2010)
- C/C++ 中的对象/结构对齐
- #pragma pack,模板类型和结构对齐
- Fscanf和结构对齐
- c++中的结构对齐和填充