Visual C++ equivalent of GCC's __attribute__ ((__packed__))
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...
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).