Can you nest C preprocessor directives?

For example, the following is possible:

#define definer(x) #define #x? 
+4
source share
6 answers

Although your syntax is invalid, the answer to your question is technically yes. But this can only be achieved with disgusting tricks that make your code unreadable and unbearable.

See also: http://www.ioccc.org/years.html#1995_vanschnitz and http://www.ioccc.org/years.html#2004_vik2

0
source

No, you cannot do this.
The pound symbol ( # ) has a different meaning in the definition. this means that if this is an argument, make it a string by specifying it.

+9
source

You cannot embed C preprocessor directives. Fortunately, this is almost never needed. If you really need that kind of power, you will almost certainly be better off with another preprocessor that you run before passing code to the C compiler. For example:

 sed 's/@ CUSTOMER@ /J. Random Person/' foo.c.in > foo.c cc foo.c 

Another useful trick is to isolate the hype in one header file, which is created by a program that you write yourself:

 ./generate-trickery --greet 'J. Random Person' > foo.h 

where foo.h will look something like this:

 #define GREET(x) ("J. Random Person greets you, " #x) 

If you link this together with a Makefile or some other automation, it will be quite seamless and not delay your development.

+8
source

No, you cannot do this.

You can reference one macro of another, but you cannot define one macro of another.

+3
source

If you are trying to create a preprocessor code segment that can be called multiple times to do slightly different things, one (moderately awful) way to do this is to isolate the code in a single .h file, which you then #include several times. The idea is that every time you #include file that you call your subroutine, you “pass arguments”, first #define with some preprocessor constants, which include the included file.

One of the places I've seen this is useful when creating smart enumerations that can be converted to / from their "string" forms (which is useful for input / output). You create a .h file containing, for example,

 ENUMVAL(foo) ENUMVAL(bar) ENUMVAL(baz) 

and then later #include this file twice: once when ENUMVAL() is defined in such a way as to create an enum declaration, and once when ENUMVAL() is defined in such a way as to create an array of string names. By doing this this way, you do not need to list the actual tokens more than once.

+3
source
 #define definer(x) #define #x? 

#x is the string x. You cannot #define a string token. (#define "foo".) It must be the identifier [a-zA-Z0-9 _] * .

You cannot nest #define like this. You cannot have #define in #define.

You can have #if inside #if blocks.

 #ifdef FOO #ifdef BAR ... #else // BAR ... #endif // BAR #else // FOO ... #endif //FOO 

You are also somewhat limited to expressions that you can use in #if macros. But sometimes you can get around this. For instance:

  /* Use CONCATENATE_4_AGAIN to expand the arguments to CONCATENATE_4 */ #define CONCATENATE_4( a,b,c,d) CONCATENATE_4_AGAIN(a,b,c,d) #define CONCATENATE_4_AGAIN(a,b,c,d) a ## b ## c ## d /* Creates a typedef that legal/illegal depending on EXPRESSION. * * Note that IDENTIFIER_TEXT is limited to "[a-zA-Z0-9_]*". * * (This may be replaced by static_assert() in future revisions of C++.) */ #define STATIC_ASSERT( EXPRESSION, IDENTIFIER_TEXT) \ typedef char CONCATENATE_4( static_assert____, IDENTIFIER_TEXT, \ ____failed_at_line____, __LINE__ ) \ [ (EXPRESSION) ? 1 : -1 ] 

Plus something like:

 STATIC_ASSERT( sizeof(int1) == 1, sizeof_int1_equal_1 ); 

(Yes, I know about #include <stdint.h>. This is just an example.)

+2
source

All Articles