How can I use "sizeof" in a preprocessor macro?

Solution:

There are several ways of doing this. Following snippets will produce no code if sizeof(someThing) equals PAGE_SIZE; otherwise they will produce a compile-time error.

1. C11 way

Starting with C11 you can use static_assert (requires #include <assert.h>).

Usage:

static_assert(sizeof(someThing) == PAGE_SIZE, "Data structure doesn't match page size");

2. Custom macro

If you just want to get a compile-time error when sizeof(something) is not what you expect, you can use following macro:

#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))

Usage:

BUILD_BUG_ON( sizeof(someThing) != PAGE_SIZE );

This article explains in details why it works.

3. MS-specific

On Microsoft C++ compiler you can use C_ASSERT macro (requires #include <windows.h>), which uses a trick similar to the one described in section 2.

Usage:

C_ASSERT(sizeof(someThing) == PAGE_SIZE);

Is there anyway to use a "sizeof" in a pre-processor macro?

No. The conditional directives take a restricted set of conditional expressions; sizeof is one of the things not allowed.

Preprocessing directives are evaluated before the source is parsed (at least conceptually), so there aren't any types or variables yet to get their size.

However, there are techniques to getting compile-time assertions in C (for example, see this page).


I know it's a late answer, but to add on to Mike's version, here's a version we use that doesn't allocate any memory. I didn't come up with the original size check, I found it on the internet years ago and unfortunately can't reference the author. The other two are just extensions of the same idea.

Because they are typedef's, nothing is allocated. With the __LINE__ in the name, it's always a different name so it can be copied and pasted where needed. This works in MS Visual Studio C compilers, and GCC Arm compilers. It does not work in CodeWarrior, CW complains about redefinition, not making use of the __LINE__ preprocessor construct.

//Check overall structure size
typedef char p__LINE__[ (sizeof(PARS) == 4184) ? 1 : -1];

//check 8 byte alignment for flash write or similar
typedef char p__LINE__[ ((sizeof(PARS) % 8) == 0) ? 1 : 1];

//check offset in structure to ensure a piece didn't move
typedef char p__LINE__[ (offsetof(PARS, SUB_PARS) == 912) ? 1 : -1];

Tags:

C

Gcc