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

Can sizeof be used in a preprocessor macro?

For example, for many years, when I wanted to do something like:

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

The exact thing that I am checking here is completely compiled - the fact is that I often like such time checks (size or alignment) to check compilation time, to protect someone changing the data structure that might have changed or changed the size of things that can break them.

Needless to say, I cannot use sizeof described above.

+66
c gcc
Nov 02 2018-10-11T00:
source share
10 answers

In any case, should you use " sizeof " in the macro process of the pre-processor?

No. Conditional directives accept a limited set of conditional expressions; sizeof is one of the things that are not allowed.

The preprocessing directives are evaluated before the source code is analyzed (at least conceptually), so there are no types or variables to get their size.

However, there are methods for obtaining compile-time statements in C (for example, see this page ).

+56
Nov 02 '10 at 15:35
source share

There are several ways to do this. The following snippets do not issue code if sizeof(someThing) is PAGE_SIZE ; otherwise, they will produce a compile-time error.

1. C ++ 11 way

Starting with C ++ 11 you can use static_assert .

Using:

 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) not what you expect, you can use the following macro:

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

Using:

 BUILD_BUG_ON( sizeof(someThing) != PAGE_SIZE ); 

This article explains in detail why it works.

3. MS-specific

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

Using:

 C_ASSERT(sizeof(someThing) == PAGE_SIZE); 
+35
Aug 29 '13 at 12:58
source share

I know this thread is really old, but ...

My decision:

 extern char __CHECK__[1/!(<<EXPRESSION THAT SHOULD COME TO ZERO>>)]; 

As long as this expression is zero, it compiles fine. Something else, and it explodes right there. Since the variable is extern'd, it does not take up space, and as long as no one refers to it (that they will not), it will not cause a communication error.

Not as flexible as the assert macro, but I couldnโ€™t get it to compile in my version of GCC, and it will be ... and I think it will compile anywhere.

+8
Oct 29 '14 at 20:12
source share

How about the following macro:

 /* * Simple compile time assertion. * Example: CT_ASSERT(sizeof foo <= 16, foo_can_not_exceed_16_bytes); */ #define CT_ASSERT(exp, message_identifier) \ struct compile_time_assertion { \ char message_identifier : 8 + !(exp); \ } 

For example, in a comment, MSVC says something like:

 test.c(42) : error C2034: 'foo_can_not_exceed_16_bytes' : type of bit field too small for number of bits 
+3
Oct 14 '13 at 7:53 on
source share

I know this is a late answer, but to add to Mike's version, a version is used here that does not allocate any memory. I did not come up with an original size check, I found it on the Internet many years ago and, unfortunately, I can not refer to the author. The other two are simply extensions of the same idea.

Since they are typedef, nothing stands out. With the name __LINE__ in the name, it is always a different name, so you can copy and paste it where necessary. This works on MS Visual Studio C compilers and GCC Arm compilers. It does not work in CodeWarrior, CW complains about redefinition without using 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]; 
+2
Mar 23 '17 at 3:28
source share

#define SIZEOF(x) ((char*)(&(x) + 1) - (char*)&(x)) may work

+1
Jul 26 '13 at 8:54
source share

The existing answers simply show how to achieve the effect of โ€œcompile-time statementsโ€ depending on the type size. This may satisfy the needs of the OP in this particular case, but there are other cases where you really need a conditional preprocessor based on the type size. Here's how to do it:

Write yourself a small C program, for example:

 /* you could call this sizeof_int.c if you like... */ #include <stdio.h> /* 'int' is just an example, it could be any other type */ int main(void) { printf("%zd", sizeof(int); } 

Compile this. Write a script in your favorite scripting language that runs the above C program and captures its output. Use this output to create a C header file. For example, if you used Ruby, it might look like this:

 sizeof_int = `./sizeof_int` File.open('include/sizes.h','w') { |f| f.write(<<HEADER) } /* COMPUTER-GENERATED, DO NOT EDIT BY HAND! */ #define SIZEOF_INT #{sizeof_int} /* others can go here... */ HEADER 

Then add the rule to your Makefile or other build script that will make it run the above script to build sizes.h .

Include sizes.h wherever you need to use preprocessor conventions based on sizes.

Done!

(Have you ever typed ./configure && make to create a program? What does configure scripts do basically the same as above ...)

+1
Aug 31 '15 at 8:53
source share

As a reference to this discussion, I report that some compilers get processor time sizeof () ar.

JamesMcNellis answer is correct, but some compilers overcome this limitation (this probably violates strict ansi c).

As an example, I refer to the IAR C compiler (probably the lead for a professional microcontroller / embedded programming).

0
Jul 26 '13 at 8:38
source share

In my portable C ++ code ( http://www.starmessagesoftware.com/cpcclibrary/ ) I wanted to put a safe defender on the dimensions of some of my structures or classes.

Instead of finding a way for the preprocessor to throw an error (which cannot work with sizeof (), as indicated here), I found a solution here that causes the compiler to throw an error. http://www.barrgroup.com/Embedded-Systems/How-To/C-Fixed-Width-Integers-C99

I had to adapt this code so that it could cause an error in my compiler (xcode):

 static union { char int8_t_incorrect[sizeof( int8_t) == 1 ? 1: -1]; char uint8_t_incorrect[sizeof( uint8_t) == 1 ? 1: -1]; char int16_t_incorrect[sizeof( int16_t) == 2 ? 1: -1]; char uint16_t_incorrect[sizeof(uint16_t) == 2 ? 1: -1]; char int32_t_incorrect[sizeof( int32_t) == 4 ? 1: -1]; char uint32_t_incorrect[sizeof(uint32_t) == 4 ? 1: -1]; }; 
0
Feb 23 '15 at 20:37
source share

The sizeof operator is not available to the preprocessor, but you can pass sizeof to the compiler and check the condition at runtime:

 #define elem_t double #define compiler_size(x) sizeof(x) elem_t n; if (compiler_size(elem_t) == sizeof(int)) { printf("%d",(int)n); } else { printf("%lf",(double)n); } 
-8
Jun 30 '13 at 9:26
source share



All Articles