Wednesday, April 2, 2008

#pragma pack() across multiple platforms

Been doing more AIX porting work. Found out how badly different compilers handle the #pragma pack directive, and I'm looking for a solution that works with all of them:

First, let's look at gcc:

#pragma pack(1)
#pragma pack()

Simple enough. I can set the packing to 1 byte, do some stuff, and then set it back to the previous value with an empty argument.

Under AIX, the xlC compiler throws a warning if you specify an empty value with the above code:

1540-1404 (W) The parameter "" specified for "pragma pack" is not valid. The pragma is ignored.

So under xlC, setting it back requires me use the "pop" keyword such as the following:

#pragma pack(1)
#pragma pack(pop)

It's treating it like a stack, which is fine. However, if you use this code under gcc, you get the following error:

warning: #pragma pack (pop) encountered without matching #pragma pack (push, <n>)

Hmmm... So, let's explicitly push the value on when I set change the packing in the first place:

#pragma pack(push, 1)
#pragma pack(pop)

Except that doesn't work because xlC doesn't recognize the push keyword. What kind of compiler knows about has a "pop" without a corresponding "push"? IBM's compiler, apparently

So in summary, xlC always treats it like a stack, GCC only treats it like a stack if you explicitly say "push", but xlC doesn't support the "push" keyword. Argh.

Here's gcc definition for #pragma pack()

MSVC appears to support the same feature set as gcc, but it also supports optional identifiers.

xLC actually claims to support "#pragma pack()" with no arguments in it's documentation (and in fact has it in one of it's examples, except it doesn't actually work..

I guess I'm going to have to do a #define for xlC's compiler