Why would the size of a packed structure be different on Linux and Windows when using gcc?

夙愿已清 提交于 2019-11-30 14:37:26

问题


In the code below, why is the size of the packed structure different on Linux and Windows when compiled with gcc?

#include <inttypes.h>
#include <cstdio>

// 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 versions used:

$ 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)

Compile and test:

$ 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.

The Linux binary prints the expected size of 7 bytes, the Windows binary 8 bytes. Why the difference?


回答1:


Section 6.37.3 of the gcc attributes explains it as a difference in ABI specs, see here: http://gcc.gnu.org/onlinedocs/gcc/Type-Attributes.html




回答2:


gcc 4.7.0 does it this way to be compatible with 64-bit MSVC++. If you want to pack the structure properly, compile with -mno-ms-bitfields. (But then your layout will be incompatible with MSVC++.)




回答3:


The attribute((packed)) is compiler-specific to GCC. Hence, that code won't even compile with MSVC++. Maybe you used another compiler for Windows, though. However, with MSVC++ you could do this:

#include <stdint.h>
#include <cstdio>

// 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;
}

and the struct will be 7 bytes.




回答4:


This is all about attribute and word alignment in memory

see if you write

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

then linux & windows both have size 8

but when you specify attribute to avoid default world allignment then

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

then in linux because of attritube size becomes 7

see gcc spec says that

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. 



回答5:


Update. Latest MinGW works fine.

Both g++ (i686-win32-dwarf-rev0, Built by MinGW-W64 project) 8.1.0 and g++ (x86_64-win32-seh-rev0, Built by MinGW-W64 project) 8.1.0 prints sizeof() of sample code is exactly equal 7 bytes.



来源:https://stackoverflow.com/questions/7789668/why-would-the-size-of-a-packed-structure-be-different-on-linux-and-windows-when

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!