Structure size check at compile time

J

John Smith

Hi

I'm porting some C++ code to new platforms and have some 1-byte aligned
structures which need a specific size. Since datatypes can vary on different
platforms (which I found out the hard way since longs are not the same size
on win64 and linux x64) I would like to do a check at compile time to make
sure things are correct. This will ease future work.

Is it possible to do something like the following at preprocessing stage:

typedef struct _aaa
{
UINT32 a;
UINT16 b;
}aaa;

#if sizeof(aaa) != (4 + 2)
#error "Wrong settings for this platform"
#endif

The compiler seems to fail no matter which platform I use. I know I can do
this at runtime but it's not useful code so I rather not have it done at
runtime. The only alternative is to enable it as a runtime check when
compiling in debug mode.

Thanks in advance.

-- John
 
N

Neelesh Bodas

John said:
Hi
Is it possible to do something like the following at preprocessing stage:

Not at preprocessing, but at compile time.
typedef struct _aaa
{
UINT32 a;
UINT16 b;
}aaa;

Isn't this same as
struct aaa {
UNIT32 a;
UINT16 b;
};

Also, UNIT32 and UNIT16 are not std C++ types . So I believe that they
are platform dependent typedefs or new type definitions.
#if sizeof(aaa) != (4 + 2)

This doesnot work because sizeof is a _compile-time_ operator, and it
is being used at preprocessing time
#error "Wrong settings for this platform"
#endif

Something on the lines of CTAssert (Ref. Modern C++ Design)

template<int i> class CorrectSize;
template<> class CorrectSize<6> {
};

int main()
{
CorrectSize<sizeof(aaa)>(); // Gives compile time error if
sizeof(aaa) is anything other than 6
}
 
R

Rennie deGraaf

John said:
Hi

I'm porting some C++ code to new platforms and have some 1-byte aligned
structures which need a specific size. Since datatypes can vary on different
platforms (which I found out the hard way since longs are not the same size
on win64 and linux x64) I would like to do a check at compile time to make
sure things are correct. This will ease future work.

Is it possible to do something like the following at preprocessing stage:

typedef struct _aaa
{
UINT32 a;
UINT16 b;
}aaa;

#if sizeof(aaa) != (4 + 2)
#error "Wrong settings for this platform"
#endif

The compiler seems to fail no matter which platform I use. I know I can do
this at runtime but it's not useful code so I rather not have it done at
runtime. The only alternative is to enable it as a runtime check when
compiling in debug mode.

Thanks in advance.

-- John

Does your *preprocessor* really evaluate the size of objects? I bet
that's your problem right there. At best, the result of a "sizeof"
isn't known until the compiler runs, and at worst, it isn't known until
run time. Assuming that your struct's size can be evaluated at
compile-time and your compiler is suffiently smart, just put something
like this at the begining of your program (warning: not tested):

if (sizeof(aaa) != (4 + 2))
{
cerr << "Wrong settings for this platform" << endl;
abort();
}

On platforms where the size of the struct really is 6, the compiler will
detect that the condition is always false and optimize it out
completely. On platforms where it isn't, the compiler might even
optimize out the rest of the program.

If you must check this at compile time, I'd suggest putting a check into
your build system. GNU autoconf, for instance, will allow you to
compile and run a trivial program that checks the size of your struct,
and trigger an alert if it's not the size you expected before attempting
to compile your program.

Rennie deGraaf
 
A

ashaniray

you may want to do something like this:

//////////////////////////////////////////////////
template<int i> class ThrowError;
template<> class ThrowError<0>
{
public:
enum {val = 0};
};

template<class T, int expected_size>
class CheckSize
{
enum { value = (sizeof(T) == expected_size) ? 0 : 1};
enum { errval = ThrowError<value>::val };
};

/////////////////////////////////////////////////////
class Test
{
UINT32 i;
};

int main()
{
CheckSize<Test, 4>(); // compiles ok, sizeof Test is 4 bytes
CheckSize<Test, 8>(); // compilation, error, size is incorrect
return 0;
}
 
R

Rolf Magnus

Rennie said:
Does your *preprocessor* really evaluate the size of objects? I bet
that's your problem right there. At best, the result of a "sizeof"
isn't known until the compiler runs, and at worst, it isn't known until
run time.

sizeof is always evaluated at compile time, but not by the preprocessor.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,764
Messages
2,569,565
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top