Take the 2-minute tour ×

I have some fairly generic code which uses preprocessor macros to add a certain prefix onto other macros. This is a much simplified example of what happens:

#define MY_VAR(x) prefix_##x

"prefix_" is actually defined elsewhere, so it will be different each time the file is included. It works well, but now I have some code I would like to skip if one of the tokens doesn't exist, but this doesn't work:

#if defined MY_VAR(hello)

What I want it to expand to is this:

#ifdef prefix_hello

But I can't figure out how. I need to use the MY_VAR() macro to do the expansion, so I can't just hardcode the name. (It's actually for some testing code, the same code gets included with a different prefix each time to test a bunch of classes, and I want to skip a couple of tests for a handful of the classes.)

Is this possible with the C++ preprocessor?


Here is some semi-compilable code to demonstrate the problem further: (to avoid squishing it into the comments below)

#define PREFIX hello

#define DO_COMBINE(p, x)  p ## _ ## x
#define COMBINE(p, x)     DO_COMBINE(p, x)
#define MY_VAR(x)         COMBINE(PREFIX, x)

// MY_VAR(test) should evaluate to hello_test

#define hello_test "blah blah"

// This doesn't work
#ifdef MY_VAR(test)
  printf("%s\n", MY_VAR(test));
share|improve this question
See: stackoverflow.com/questions/1489932/…; see also stackoverflow.com/questions/195975/… for stringification (which is quite similar in many ways) –  Jonathan Leffler Apr 24 '10 at 6:51
The stringification works fine, the problem arises with the #ifdef, which doesn't seem to be covered in those other questions. –  Malvineous Apr 25 '10 at 6:30
Are any of these answers acceptable or helpful? :) –  Joseph Quinsey May 20 '10 at 21:51
Sorry yes, the answer seems to be "it's not possible but you can work around it" so I've marked the one with the simplest workaround as the accepted answer. –  Malvineous May 22 '10 at 6:09
add comment

3 Answers

up vote 1 down vote accepted

Is there more to your program than this question describes? The directive

#define MY_VAR(x) prefix_##x

defines exactly one preprocessor identifier. The call

blah ^&* blah MY_VAR(hello) bleh <>? bleh

simply goes in one end of the preprocessor and comes out the other without defining anything.

Without some other magic happening, you can't expect the preprocessor to remember what arguments have been passed into what macros over the course of the preceding source code.

You can do something like

#define prefix_test 1
#if MY_VAR(test) == 1
#undef prefix_test // optional, "be clean"
#undef prefix_test

to query whether the prefix currently has the particular value prefix_. (Undefined identifiers are replaced with zero.)

share|improve this answer
Have you tried to compile that? "#if MY_VAR(test) == 1" doesn't work with my compiler. –  Malvineous Apr 25 '10 at 6:27
@Malvineous: Yep, works fine for me. GCC. What goes wrong for you? –  Potatoswatter Apr 25 '10 at 6:37
@Potatoswatter: test.c:2:11: error: missing binary operator before token "(", this is GCC 4.4.2 –  Malvineous Apr 25 '10 at 8:39
@Malvineous: Is MY_VAR defined? I meant you can use this with your example code, not that MY_VAR is a standard function. –  Potatoswatter Apr 25 '10 at 14:54
Ah of course, sorry. I've investigated your solution further and it seems that it works because it's not using #ifdef. If I use #if and check that the value equals something it works, but because I don't know what the value is I need to check whether it just exists. It also seems a bit unreliable with strings. I have updated the question with some example code that hopefully explains this a bit better! –  Malvineous May 3 '10 at 0:42
show 1 more comment

I think you've got to the level where the preprocessor won't cut it any more; it's really quite simple-minded. Have you considered using templates instead? (Assuming that they're meaningful for your problem, of course.)

share|improve this answer
Of course, if it can do it then I've got some code to rewrite... ;-) –  Donal Fellows Apr 24 '10 at 7:08
Thanks for the suggestion. I've been using the macros because they're quick and easy, but if they won't cut it any more I guess I will have to investigate alternatives like templates! –  Malvineous Apr 24 '10 at 7:16
Note that macros can be expanded inside of #if directives; it's just that this is a case where you can't, probably because the compiler can't parse parenthesis in the argument of defined. –  Joey Adams Apr 24 '10 at 7:45
@Joey: That was what I understood too. –  Donal Fellows Apr 24 '10 at 7:47
add comment

This is in response to your updated question. For each possible hello_test, after any possibility of #define hello_test "blah blah", add the lines:

#ifndef hello_test
#define hello_test (char*)0

Then change your test to:

if (MY_VAR(test))

Or, as an alternative, before all the #define ..."blah blah"'s, add the line(s):

static const char * const MY_VAR(test);

for all possible values of MY_VAR and test. This will avoid hard-coding "hello_test". (The second const here removes the gcc warning: ‘hello_test’ defined but not used.)

share|improve this answer
Interesting idea - however I'm not so keen on declaring a whole bunch of variables for things that might be compiled in or out - I don't think compilers are smart enough to omit those variables from the compiled code even if they're unused. –  Malvineous May 22 '10 at 6:10
add comment

Your Answer


