Reputation: 2575
I have a problem that a struct shall be checked - at compile time - if it is well aligned or if it contains gaps. The checking may be done in additional test code, but I don't want "packed" data in the real implementation code.
This is an example header file (MyData.h) with the typical include guards:
#ifndef MYDATA_H_
#define MYDATA_H_
struct uneven
{
int bla_u32;
short bla_u16;
char bla_u8;
/* <-- this gap will be filled in the unpacked version */
};
#endif // MYDATA_H
I found one possible solution - see below.
Questions:
Is there an elegant way to check if the struct uneven
contains a different number of bytes compared to its unpacked counterpart at compile time?
Is there maybe even a solution that will work in C (without using a namespace)?
Upvotes: 13
Views: 1731
Reputation: 5668
You could use a function instead of a namespace (on ideone):
This solution also works in C
Header File:
typedef struct
{
int bla_u32;
short bla_u16;
char bla_u8;
/* <-- this gap will be filled in the unpacked version */
} uneven;
Source File:
#include "MyData.h"
#define StaticAssert(cond, msg) switch(0){case 0:case cond:;}
void checkSizes()
{
uneven unpacked_uneven;
#pragma pack(push, 1)
#undef MYDATA_H_ // force re-including "MyData.h"
#include "MyData.h"
#pragma pack(pop)
uneven packed_uneven;
StaticAssert(sizeof(unpacked_uneven) == sizeof(packed_uneven), "uneven contains gaps");
}
You can place your StaticAssert
into the function for a compile time error.
Upvotes: 4
Reputation: 238461
A compiler specific solution that works for both C and C++: GCC has a warning option -Wpadded
, that produces a warning for every definition that change size due to alignment.
Upvotes: 5
Reputation: 2575
I found one (somehow nasty and very tricky) solution for the problem that only works with C++, not C.
#define StaticAssert(cond, msg) switch(0){case 0:case cond:;}
#pragma pack(push, 1)
namespace packed
{
#include "MyData.h"
}
#pragma pack(pop)
#undef MYDATA_H_ // force re-including "MyData.h"
#include "MyData.h"
void checkSizes()
{
StaticAssert(sizeof(packed::uneven) == sizeof(uneven), "uneven contains gaps");
}
This StaticAssert
macro fails for the given uneven struct data - as the packed version's size is of 7 bytes and the unpacked (normal) version is 8 bytes. If an additional char
is added at the end of the struct the test succeeds - both versions have 8 bytes then.
Upvotes: 2