使用gcc时,为什么在Linux和Windows上打包结构的大小会有所不同?

在下面的代码中,为什么在使用gcc编译时,在Linux和Windows上打包结构的大小是不同的?

#include  #include  // id3 header from an mp3 file struct header { uint8_t version[ 2 ]; uint8_t flags; uint32_t size; } __attribute__((packed)); int main( int argc, char **argv ) { printf( "%u\n", (unsigned int)sizeof( header ) ); return 0; } 

使用的gcc版本:

 $ g++ --version g++ (Ubuntu/Linaro 4.5.2-8ubuntu4) 4.5.2 $ x86_64-w64-mingw32-g++ --version x86_64-w64-mingw32-g++ (GCC) 4.7.0 20110831 (experimental) 

编译和测试:

 $ g++ -Wall packed.cpp -o packed && ./packed 7 $ x86_64-w64-mingw32-g++ -Wall packed.cpp -o packed.exe --> prints '8' when run on Windows. 

Linux二进制文件打印7字节的预期大小,Windows二进制8字节。 为什么不同?

gcc属性的第6.37.3节将其解释为ABI规范的不同之处,请参见此处: http ://gcc.gnu.org/onlinedocs/gcc/Type-Attributes.html

gcc 4.7.0这样做是为了与64位MSVC ++兼容。 如果要正确打包结构,请使用-mno-ms-bitfields编译。 (但是你的布局将与MSVC ++不兼容。)

属性 ((packed))是特定于编译器的GCC。 因此,该代码甚至不能用MSVC ++编译。 也许您在Windows上使用了另一个编译器。 但是,使用MSVC ++,您可以这样做:

 #include  #include  // id3 header from an mp3 file #pragma pack(push,1) struct header { uint8_t version[ 2 ]; uint8_t flags; uint32_t size; }; #pragma pack(pop) int main( int argc, char **argv ) { printf( "%u\n", (unsigned int)sizeof( header ) ); return 0; } 

结构将是7个字节。

这完全是关于内存中的属性单词对齐

看你是否写作

 struct header { uint8_t version[ 2 ]; uint8_t flags; uint32_t size; }; 

那么linux和windows的大小都是8

但是当你指定属性以避免默认世界对齐时

 struct header { uint8_t version[ 2 ]; uint8_t flags; uint32_t size; } __attribute__((packed)); 

然后在linux中因为attritube大小变为7

看gcc spec说的那样

 If packed is used on a structure, or if bit-fields are used it may be that the Microsoft ABI packs them differently than GCC would normally pack them.