How two check struct size at compile time

F

FTSoJ

On a file A.c I define the structure T1
typedef struct {
int dummy;
int age;
char lastname [128];
char firstname[128];
} T1_user;


On a file B.c I define a strcuture T2

typedef struct {
int id;
int age;
char dummy[256]
} T2_id;

I would like to generate an error during compilation if sizeof (T1)
differ from sizeof(T2).
I tried
#if sizeof(T2_id) != sizeof(T1_user)
#error "Size of T1_user differ from T2_id, compile abort!"
#endif


But it fails on metrowerks as on GCC.

This is a sample, in real T1 from Tn are unions and I would like to
guaranty that interprocess exchange can't lead to buffer overflow if one
Tn type is modified in the future.

Regards,

- François -
 
S

S.Tobias

FTSoJ said:
#if sizeof(T2_id) != sizeof(T1_user)
#error "Size of T1_user differ from T2_id, compile abort!"
#endif

Preprocessor will not do it, you have to trick the compiler
to do it for you.
Google for "CCASSERT", a handy invention in this group.
 
C

Christian Bau

FTSoJ said:
On a file A.c I define the structure T1
typedef struct {
int dummy;
int age;
char lastname [128];
char firstname[128];
} T1_user;


On a file B.c I define a strcuture T2

typedef struct {
int id;
int age;
char dummy[256]
} T2_id;

I would like to generate an error during compilation if sizeof (T1)
differ from sizeof(T2).
I tried
#if sizeof(T2_id) != sizeof(T1_user)
#error "Size of T1_user differ from T2_id, compile abort!"
#endif

Try these two:

char* p = 0;
char* q = 1;

One compiles, the other doesn't. The reason is that 0 is a "null pointer
constant" and will be converted to a null pointer when needed, 1 isn't
and assigning an int to a char* is not allowed.

Say you want to verify at compile time that sizeof (T2_id) == sizeof
(T1_user). The expression

sizeof (T2_id) != sizeof (T1_user)

is 0 if the sizes are the same, and 1 if the sizes are different.
Therefore

char* p = (sizeof (T2_id) != sizeof (T1_user));

will compile if the sizes are the same and won't compile if the sizes
are different. Now pack that into a nice macro for readability, and
that's it.
 
J

jacob navia

Christian said:
On a file A.c I define the structure T1
typedef struct {
int dummy;
int age;
char lastname [128];
char firstname[128];
} T1_user;


On a file B.c I define a strcuture T2

typedef struct {
int id;
int age;
char dummy[256]
} T2_id;

I would like to generate an error during compilation if sizeof (T1)
differ from sizeof(T2).
I tried
#if sizeof(T2_id) != sizeof(T1_user)
#error "Size of T1_user differ from T2_id, compile abort!"
#endif


Try these two:

char* p = 0;
char* q = 1;

One compiles, the other doesn't. The reason is that 0 is a "null pointer
constant" and will be converted to a null pointer when needed, 1 isn't
and assigning an int to a char* is not allowed.

Say you want to verify at compile time that sizeof (T2_id) == sizeof
(T1_user). The expression

sizeof (T2_id) != sizeof (T1_user)

is 0 if the sizes are the same, and 1 if the sizes are different.
Therefore

char* p = (sizeof (T2_id) != sizeof (T1_user));

will compile if the sizes are the same and won't compile if the sizes
are different. Now pack that into a nice macro for readability, and
that's it.

VERY clever. Neever thought about it!
 
A

Alex Fraser

[snip]
I would like to generate an error during compilation if sizeof (T1)
differ from sizeof(T2).
I tried
#if sizeof(T2_id) != sizeof(T1_user)
#error "Size of T1_user differ from T2_id, compile abort!"
#endif

But it fails on metrowerks as on GCC.

This is a sample, in real T1 from Tn are unions and I would like to
guaranty that interprocess exchange can't lead to buffer overflow if one
Tn type is modified in the future.

Instead of trying to ensure they are all the same size, perhaps you could
make the code insensitive to different sizes - for example, by putting them
all in a union and using that as the unit for "interprocess exchange".

Alex
 
J

Jason Curl

FTSoJ said:
On a file A.c I define the structure T1
typedef struct {
int dummy;
int age;
char lastname [128];
char firstname[128];
} T1_user;


On a file B.c I define a strcuture T2

typedef struct {
int id;
int age;
char dummy[256]
} T2_id;

I would like to generate an error during compilation if sizeof (T1)
differ from sizeof(T2).
I tried
#if sizeof(T2_id) != sizeof(T1_user)
#error "Size of T1_user differ from T2_id, compile abort!"
#endif


But it fails on metrowerks as on GCC.

This is a sample, in real T1 from Tn are unions and I would like to
guaranty that interprocess exchange can't lead to buffer overflow if one
Tn type is modified in the future.

The only solutions I've seen in API's is to pass the length of the
structure at the beginning of the structure, and use run-time checking
to protect against overflows.
 
O

Old Wolf

Christian said:
char* p = (sizeof (T2_id) != sizeof (T1_user));

will compile if the sizes are the same and won't compile if the
sizes are different. Now pack that into a nice macro for
readability, and that's it.

Another of the many options is:

typedef char p[ (sizeof(T2) == sizeof(T1)) ? 1 : -1];

because you can't have an array type with negative bound.
Also this option won't actually declare a variable and
potentially use up memory, and is more likely (IME) to
cause the compiler to stop compilation.

If you make this a macro, you probably want to roll
__LINE__ into it, otherwise if you use the macro twice in the
same scope, the compiler will complain about a re-declared
variable.

For a pre-existing solution, check out STATIC_ASSERT in the
preprocessor section of http://www.boost.org/
 

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,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top