结构大小和内存布局取决于#pragma pack
Structure size and memory layout depending on #pragma pack
考虑下面用vc++ 2010编译的程序:
#pragma pack(push, 1) // 1, 2, 4, 8
struct str_test
{
unsigned int n;
unsigned short s;
unsigned char b[4];
};
#pragma pack(pop)
int main()
{
str_test str;
str.n = 0x01020304;
str.s = 0xa1a2;
str.b[0] = 0xf0;
str.b[1] = 0xf1;
str.b[2] = 0xf2;
str.b[3] = 0xf3;
unsigned char* p = (unsigned char*)&str;
std::cout << sizeof(str_test) << std::endl;
return 0;
}
我在return 0;
行上设置断点,并在调试器中查看内存窗口,从地址p
开始。我得到以下结果(sizeof
和内存布局,取决于pack
):
// 1 - 10 (pack, sizeof)
// 04 03 02 01 a2 a1 f0 f1 f2 f3
// 2 - 10
// 04 03 02 01 a2 a1 f0 f1 f2 f3
// 4 - 12
// 04 03 02 01 a2 a1 f0 f1 f2 f3
// 8 - 12
// 04 03 02 01 a2 a1 f0 f1 f2 f3
两个问题:
为什么
sizeof(str_test)
是12包8?为什么内存布局是相同的,不依赖于包值?
为什么第8包的sizeof(str_test)是12 ?
来自MSDN文档:
成员的对齐将位于an的倍数或成员大小的倍数,以二者为准小。
在你的例子中,最大的成员是4字节,小于8,所以4字节将用于对齐。
为什么内存布局是相同的,不依赖于包的值?
编译器不允许对结构体成员重新排序,但可以填充成员。在pack 8的情况下,它执行以下操作:
#pragma pack(push, 8) // largest element is 4bytes so it will be used instead of 8
struct str_test
{
unsigned int n; // 4 bytes
unsigned short s; // 2 bytes
unsigned char b[4]; // 4 bytes
//2 bytes padding here;
};
#pragma pack(pop)
因此sizeof(str_test)将为12
嗯,似乎编译器(MSVC2010)根据类型改变填充位置,在unsigned char b[4];
的情况下,它在结构的末尾放置了两个字节填充。在您的示例中,2字节cc cc
恰好位于字符数组之后。
#pragma pack(push, 8) // largest element is 4bytes so it will be used instead of 8
struct str_test
{
unsigned int n; // 4 bytes
unsigned short s; // 2 bytes
//2 bytes padding here;
int; // 4 bytes
};
#pragma pack(pop)
我所做的是将最后一个成员从char[4]
更改为int
,并且可以通过在两种情况下分别减去最后和第一个成员的地址6和8来验证。
最后一个成员int
的内存转储如下
04 03 02 01 a2 a1 cc cc f0 f1 f2 f3
最后一个成员unsigned char[4]
的内存转储如下
04 03 02 01 a2 a1 f0 f1 f2 f3 cc cc
相关文章:
- 重载运算符new[]的行为取决于析构函数
- 在头文件和 cpp 文件中使用一次 #pragma 时出现结构重定义错误
- #pragma 包(1)会导致分段错误
- 禁止显示有关包含文件中 #pragma 包的警告
- 新的放置取决于 iostream
- Writefile() 无法写入数据,具体取决于数据的长度
- 编译时检查 #pragma 包的使用情况
- ASIO signal_set多个 IO 线程不可靠,具体取决于代码顺序?
- OpenMP #pragma omp for v/s #pragma omp parallel for 之间的区别?
- SFINAE是否取决于类型推断?
- 将强制转换简化为取决于参数的类型
- 修复"-Wunused-parameter"取决于预处理器条件的警告
- 内存中类位置的成员是否取决于类成员在类定义中的位置?
- #pragma(*诊断)当将Clang分析器与GCC编译器混合时
- 奇怪的Arduino C++编译错误取决于文件位置
- #pragma 警告不适用于 catch 语句
- CUDA 的性能取决于声明变量
- 我想要一个具有子函数的函数访问相同的命名函数,而不使用它取决于其子类的类
- 条件跳转或移动取决于 std::wistringstream 的未初始化值
- 结构大小和内存布局取决于#pragma pack