Почему размер упакованной структуры будет отличаться в Linux и Windows при использовании gcc? - PullRequest
18 голосов
/ 17 октября 2011

В приведенном ниже коде почему размер упакованной структуры различается в Linux и Windows при компиляции с 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:

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

Компилировать и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.

Двоичный файл Linux печатает ожидаемый размер 7 байт, двоичный файл Windows - 8 байт.Почему разница?

Ответы [ 5 ]

7 голосов
/ 17 октября 2011

gcc 4.7.0 делает это таким образом, чтобы быть совместимым с 64-битным MSVC ++.Если вы хотите упаковать структуру правильно, скомпилируйте с -mno-ms-bitfields.(Но тогда ваш макет будет несовместим с MSVC ++.)

4 голосов
/ 17 октября 2011

Раздел 6.37.3 атрибутов gcc объясняет это как разницу в спецификациях ABI, см. Здесь: http://gcc.gnu.org/onlinedocs/gcc/Type-Attributes.html

3 голосов
/ 17 октября 2011

Атрибут ((упакованный)) зависит от компилятора GCC.Следовательно, этот код даже не будет компилироваться с MSVC ++.Может быть, вы использовали другой компилятор для Windows, хотя.Тем не менее, с MSVC ++ вы можете сделать это:

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

и структура будет 7 байтов.

1 голос
/ 17 октября 2011

Это все о атрибут и выравнивание слов в памяти

посмотри, пишешь ли ты

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 сказано, что

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. 
0 голосов
/ 20 декабря 2018

Обновление.Последний MinGW работает отлично.

И g++ (i686-win32-dwarf-rev0, Built by MinGW-W64 project) 8.1.0, и g++ (x86_64-win32-seh-rev0, Built by MinGW-W64 project) 8.1.0 печатают sizeof () образца кода точно равно 7 байтам.

...