Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

c

gcc

Is there any way to use a sizeof in a preprocessor macro?

For example, there have been a ton of situations over the years in which I wanted to do something like:

#if sizeof(someThing) != PAGE_SIZE #error Data structure doesn't match page size #endif 

The exact thing I'm checking here is completely made up - the point is, I often like to put in these types of (size or alignment) compile-time checks to guard against someone modifying a data-structure which could misalign or re-size things which would break them.

Needless to say - I don't appear to be able to use a sizeof in the manner described above.

like image 372
Brad Avatar asked Nov 02 '10 15:11

Brad


People also ask

Can sizeof be used in macro?

The sizeof is a unary operator in C/C++ programming language, it is used to get the occupied size of a variable, constant, expression, data type, etc. It returns an unsigned integral type (size_t). Here, we will create a macro to implement own sizeof operator.

Is sizeof a preprocessor?

(Strictly, sizeof produces an unsigned integer value whose type, size_t , is defined in the header <stddef. h>.) A sizeof cannot be used in a #if directive, because the preprocessor does not parse type names. But sizeof in the #define is not evaluated by the preprocessor, so the code here is legal.

What is sizeof () in C operator function macro?

Answer: sizeof is a unary operator in the programming languages C and C++. It generates the storage size of an expression or a data type, measured in the number of char-sized units. Consequently, the construct sizeof is guaranteed to be 1.

Can sizeof be used in #if?

Because sizeof() is calculated after the preprocessor is run, so the information is not available for #if .


2 Answers

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); 
like image 56
nevermind Avatar answered Oct 06 '22 04:10

nevermind


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).

like image 20
James McNellis Avatar answered Oct 06 '22 05:10

James McNellis