Visual C++ equivalent of GCC's __attribute__ ((__packed__))

78,670

Solution 1

You can define PACK like as follows for GNU GCC and MSVC:

#ifdef __GNUC__
#define PACK( __Declaration__ ) __Declaration__ __attribute__((__packed__))
#endif

#ifdef _MSC_VER
#define PACK( __Declaration__ ) __pragma( pack(push, 1) ) __Declaration__ __pragma( pack(pop))
#endif

And use it like this:

PACK(struct myStruct
{
    int a;
    int b;
});

Solution 2

I don't know a slick way of doing it, but you could possibly do something horrible like this:

#include "packed.h"
struct Foo { /* members go here */ } PACKED;
#include "endpacked.h"

Then for MSVC, packed.h:

#define PACKED
#pragma pack(push,1)

endpacked.h

#pragma pack(pop)
#undef PACKED

For gcc, packed.h:

#define PACKED __attribute__ ((__packed__))

endpacked.h:

#undef PACKED

Fundamentally, packing is too platform-dependent. Suppose your packed struct has 8-bit fields in it, and consider some system with a 16-bit byte. It can't have a struct representing your data just by packing - you'd have to know how 8-bit bytes are converted to 16-bit bytes when transferred between the two systems. The struct on the 16bit machine might need bitfields, in which case you'd have to know how the implementation lays them out.

So if the code is intended to be generally portable, you may just have to define whatever packed structures you need in a platform-specific section of your header file. Or rather, structure your code so that a future port can do that if it has to.

Solution 3

I know this question is old now, but I believe there is a better solution than those posted earlier. It is possible to put the pragma in the MSVC case in the struct declaration line after all. Consider the following:

#ifdef _MSC_VER
#  define PACKED_STRUCT(name) \
    __pragma(pack(push, 1)) struct name __pragma(pack(pop))
#elif defined(__GNUC__)
#  define PACKED_STRUCT(name) struct __attribute__((packed)) name
#endif

Then this can be used like so:

typedef PACKED_STRUCT() { short a; int b } my_struct_t;
PACKED_STRUCT(my_other_struct) { short a; int b };

etc.

The key here is that the use of the __pragma only needs to be around the declaration line of the struct. This needs to include the struct name if it is given one, hence the name being a parameter to the macro. Of course, this is easy to extend to enum/class, which I'll leave as an exercise to the reader!

The test program on the pack documentation MSDN page is useful to verify this.

EDIT

It turns out in my testing I was using the Intel Compiler on Windows. Using icl.exe this approach works without a problem, but with the Microsoft compiler (cl.exe), it does not (tested with 2010 and 2013).

Solution 4

You can do it the other way round since GCC supports the VC++ pack related pragmas. Look here for more information.

Extract...

For compatibility with Microsoft Windows compilers, GCC supports a set of #pragma directives which change the maximum alignment of members of structures (other than zero-width bitfields), unions, and classes subsequently defined. The n value below always is required to be a small power of two and specifies the new alignment in bytes.

#pragma pack(n) simply sets the new alignment.

#pragma pack() sets the alignment to the one that was in effect when compilation started (see also command line option -fpack-struct[=<n>] see Code Gen Options).

#pragma pack(push[,n]) pushes the current alignment setting on an internal stack and then optionally sets the new alignment.

#pragma pack(pop) restores the alignment setting to the one saved at the top of the internal stack (and removes that stack entry).

Note that #pragma pack([n]) does not influence this internal stack; thus it is possible to have #pragma pack(push) followed by multiple #pragma pack(n) instances and finalized by a single #pragma pack(pop).

Some targets, e.g. i386 and powerpc, support the ms_struct #pragma which lays out a structure as the documented __attribute__((ms_struct)).

#pragma ms_struct on turns on the layout for structures declared.

#pragma ms_struct off turns off the layout for structures declared.

#pragma ms_struct reset goes back to the default layout.

Solution 5

Another solution, depending what compilers you need to support, is to notice that GCC has supported the Microsoft-style packing pragmas since at least version 4.0.4 (the online documentation is available at gnu.org for versions 3.4.6 and 4.0.4 - the pragmas are not described in the former and are in the latter). This lets you just use #pragma pack(push,1) before a structure definition and #pragma pack(pop) after the definition and it will compile in either.

Share:
78,670
Malkocoglu
Author by

Malkocoglu

I'm Malkocoglu, and you're not ! C/C++ :: rocks, (void *) makes it the king. Python :: good for hi-level, the GIL sucks. Java :: mediocre stuff, not very cool. C# :: mediocre stuff, same as java. ASM :: X86 is my ex, ARM is cool. If you debug, you'll see !

Updated on September 25, 2020

Comments

  • Malkocoglu
    Malkocoglu over 3 years

    For some compilers, there is a packing specifier for structs, for example ::

    RealView ARM compiler has "__packed"
    Gnu C Compiler has "__attribute__ ((__packed__))"
    Visual C++ has no equivalent, it only has the "#pragma pack(1)"
    

    I need something that I can put into the struct definition.

    Any info/hack/suggestion ? TIA...