George
George

Reputation: 13

Why sizeof is different on linux and VS of 32bit process? even with "#pragma pack" and "-fpack-struct"

#include "stdio.h"

#pragma pack(8)
struct testSize {
    int a;  //size 4, alignment 8
    double b;//size 8, alignment 8
};
#pragma pack()

int main(int argc, char** argv)
{
    printf("sizeof testSize %d \n", sizeof(struct testSize));
    printf("sizeof int %d , sizeof double %d\n", sizeof(int), sizeof(double));

    return 0;
}

The default max alignment of a struct is 8, and also we can set by #pragma pack(8) or -fpack-struct=8. But on 32bit process compiled with gcc, it doesn't work.

On Linux (32):

$ gcc -m32 -fpack-struct=8 -o TestSize TestSize.c
$ ./TestSize
sizeof testSize 12
sizeof int 4 , sizeof double 8

On VS (x86):

sizeof testSize 16
sizeof int 4 , sizeof double 8

On linux, the alignment seems like 4, not 8. From the doc, it's "For compatibility with Microsoft Windows compilers".

Upvotes: 0

Views: 168

Answers (2)

John Bollinger
John Bollinger

Reputation: 180361

The documentation and observed behavior of GCC are consistent with each other.

GCC Docs:

For compatibility with Microsoft Windows compilers, GCC supports a set of #pragma directives that change the maximum alignment of members of structures

[...]

#pragma pack(n) simply sets the new [maximum] alignment

The resulting size of the struct shows that GCC on Linux is aligning the double on a four-byte (or less) boundary. Four is less than 8.


The documentation and observed behavior of VS are consistent with each other.

VS Docs:

Specifies packing alignment for structure, union, and class members.

[...]

n [...] The alignment of a member will be on a boundary that is either a multiple of n or a multiple of the size of the member, whichever is smaller.

The size of a double is 8, and the specified maximum alignment is 8. The size of the structure shows that VS on Windows aligns the double on an 8-byte boundary, just as it should.


On linux, the alignment seems like 4, not 8. From the doc, it's "For compatibility with Microsoft Windows compilers".

Both compilers accept your pragma. It has no practical effect on either one. This is source compatibility with respect to the pragma.

That the default alignment rules for the two compilers differ could be taken as an incompatibility, but that's not an issue of the pragma. And in this case you can use the pragma to get the same (weaker) alignment of both structures by specifying maximum alignment 4. Or you should be able to get the stronger alignment with GCC on x86 Linux by via the -malign-double compiler option.

But note well that by looking at VS on Windows and GCC on Linux, you are comparing apples and oranges. There is no binary compatibility consideration across those platforms. Consider trying your experiment with a Windows build of GCC, such as MinGW's. I'm not in a position to test at the moment, but I anticipate that GCC on Windows will conform to Windows alignment conventions by default, and that pragma pack will affect the layout exactly the same way on the GCC/Windows as it does on VS/Windows.

Upvotes: 0

Ben Zotto
Ben Zotto

Reputation: 71018

The GCC page you link says the pragma "changes the maximum alignment". It could well be that the 8 bytes you specify is being ignored in favor of a smaller default of 4 on your compilation target.

(Packing pragmas are typically used when it's desirable to "pack tight", like to single-byte alignment, for structures that will travel over the wire or get persisted to disk in a program-agnostic sort of way. They're not generally used to enforce arbitrary alignments.)

Upvotes: 2

Related Questions