@
liuxu #17 修正一下,我之前是 32 位系统 debug 的,现在都是 64 位系统,情况有变化。
首先说结论:
1. 和编译的目标程序的位数有关,32 位程序最高是 4 字节(32 位)对齐,64 位程序最高是(8 字节)64 位对齐。
2. 在 1 的要求下,struct 中按最宽位数的变量对齐。结合 1 中的“最高”的意思是:
64 位程序:uint32_t + uint64_t + uint64_t 分配 24 字节(8+8+8)。
32 位程序:uint32_t + uint64_t + uint64_t 分配 20 字节(4+(4+4)+(4+4))。
32/64 位程序:uint8_t +uint16_t +uint8_t 分配 8 字节(2+2+2)。
3. 添加#pragma pack(4)后,32 位和 64 位程序都按 4 字节(32 位)对齐,也就是 uint32_t + uint64_t + uint64_t 都是 20 字节(4+(4+4)+(4+4))。但是如果 struct 最大为 uint16_t ,则依然按 2 字节对齐。(也就是说 pack 无法影响 struct 最大位宽限制)
4. 添加了#pragma pack(16)后,64 位依然按 8 字节(64 位)对齐。也就是说 pack 中的数字只能是不大于(系统位数 /8)的 2 的次方的数字。
所以楼主的情况, 如果代码中真的没有#pragma pack(),但是出现了帖子中的现象,只有可能是以下 3 中情况:
1. 楼主的系统是 32 位的。( 32 位系统只会运行 32 位编译器编译出 32 位程序)
2. 楼主的编译器是 32 位的。( 32 位编译器只会编译出 32 位程序)
3. 楼主 64 位 msvc 编译目标选择的是 32 位程序。(据我所知 vs 默认的 debuging 版本编译的是 32 位程序,至少我几年前 debug 的时候是的,也有可能是我创建项目的时候设置成了 32 位)。
即楼主 2 次编译的字节对齐方式为:
struct FixedLengthHeader {
uint32_t HeaderSize = 0;
uint64_t CryptogramSize = 0;
uint64_t ReservedField = 0;
}FixedPackageHeaders;
20 字节(4+(4+4)+(4+4))。
struct FixedLengthHeader {
uint32_t HeaderSize = 0;
uint64_t CryptogramSize = 0;
uint8_t DevFlag = 0;
uint8_t HeaderVer = 0;
uint32_t PackagerVer = 0;
uint16_t Reserved = 0
}FixedPackageHeaders;
24 字节(4+(4+4)+4+4+4)。
以上是 64 位 linux gcc 下的结果推测的 msvc 的结果,windows 下的实际结果还是得大佬们自己调试。
以下是我 GDB 打印情况:
系统:Ubuntu 20.04.3 LTS x86_64
gcc: gcc (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
没有添加#progma pack(4),编译指令:gcc -g test.c
/* offset | size */ type = struct FixedLengthHeader {
/* 0 | 4 */ uint32_t HeaderSize;
/* XXX 4-byte hole */
/* 8 | 8 */ uint64_t CryptogramSize;
/* 16 | 8 */ uint64_t ReservedField;
/* total size (bytes): 24 */
}
(8+8+8)
/* offset | size */ type = struct FixedLengthHeader {
/* 0 | 4 */ uint32_t HeaderSize;
/* XXX 4-byte hole */
/* 8 | 8 */ uint64_t CryptogramSize;
/* 16 | 1 */ uint8_t DevFlag;
/* 17 | 1 */ uint8_t HeaderVer;
/* XXX 2-byte hole */
/* 20 | 4 */ uint32_t PackagerVer;
/* 24 | 2 */ uint16_t Reserved;
/* XXX 6-byte padding */
/* total size (bytes): 32 */
}
(8+8+8)
/* offset | size */ type = struct FixedLengthHeader {
/* 0 | 4 */ uint32_t HeaderSize;
/* 4 | 1 */ uint8_t DevFlag;
/* 5 | 1 */ uint8_t HeaderVer;
/* XXX 2-byte hole */
/* 8 | 4 */ uint32_t PackagerVer;
/* 12 | 2 */ uint16_t Reserved;
/* XXX 2-byte padding */
/* total size (bytes): 16 */
}
(4+4+4+4)
没有添加#progma pack(4),编译指令:gcc -m32 -g test.c
/* offset | size */ type = struct FixedLengthHeader {
/* 0 | 4 */ uint32_t HeaderSize;
/* 4 | 8 */ uint64_t CryptogramSize;
/* 12 | 8 */ uint64_t ReservedField;
/* total size (bytes): 20 */
}
(4+(4+4)+(4+4))
/* offset | size */ type = struct FixedLengthHeader {
/* 0 | 4 */ uint32_t HeaderSize;
/* 4 | 8 */ uint64_t CryptogramSize;
/* 12 | 1 */ uint8_t DevFlag;
/* 13 | 1 */ uint8_t HeaderVer;
/* XXX 2-byte hole */
/* 16 | 4 */ uint32_t PackagerVer;
/* 20 | 2 */ uint16_t Reserved;
/* XXX 2-byte padding */
/* total size (bytes): 24 */
}
(4+(4+4)+4+4+4)
添加#progma pack(4),编译指令:gcc -g test.c
/* offset | size */ type = struct FixedLengthHeader {
/* 0 | 4 */ uint32_t HeaderSize;
/* 4 | 8 */ uint64_t CryptogramSize;
/* 12 | 8 */ uint64_t ReservedField;
/* total size (bytes): 20 */
}
(4+(4+4)+(4+4))
/* offset | size */ type = struct FixedLengthHeader {
/* 0 | 4 */ uint32_t HeaderSize;
/* 4 | 8 */ uint64_t CryptogramSize;
/* 12 | 1 */ uint8_t DevFlag;
/* 13 | 1 */ uint8_t HeaderVer;
/* XXX 2-byte hole */
/* 16 | 4 */ uint32_t PackagerVer;
/* 20 | 2 */ uint16_t Reserved;
/* XXX 2-byte padding */
/* total size (bytes): 24 */
}
(4+(4+4)+4+4+4)
添加#progma pack(16),编译指令:gcc -g test.c
/* offset | size */ type = struct FixedLengthHeader {
/* 0 | 4 */ uint32_t HeaderSize;
/* XXX 4-byte hole */
/* 8 | 8 */ uint64_t CryptogramSize;
/* 16 | 1 */ uint8_t DevFlag;
/* 17 | 1 */ uint8_t HeaderVer;
/* XXX 2-byte hole */
/* 20 | 4 */ uint32_t PackagerVer;
/* 24 | 2 */ uint16_t Reserved;
/* XXX 6-byte padding */
/* total size (bytes): 32 */
}
(8+8+8+8)