70

I want to write a macro that spits out code based on the Boolean value of its parameter. So say DEF_CONST(true) should be expanded into const, and DEF_CONST(false) should be expanded into nothing.

Clearly the following doesn't work because we can't use another preprocessor inside #defines:

#define DEF_CONST(b_const) \
#if (b_const) \
  const \
#endif
3
  • 4
    What is the point of this? Do you have a concrete example, because this seems rather strange... Commented May 14, 2010 at 5:06
  • See also <stackoverflow.com/questions/8427963/if-inside-define>. Commented Dec 8, 2011 at 9:31
  • 1
    @DeanHarding Didn't exist at the time of your comment, but _Generic is an example. You may need to check if uintmax_t has a different underlying type than unsigned long long. Commented Jul 8, 2021 at 15:19

2 Answers 2

70

You can simulate conditionals using macro token concatenation as follows:

#define DEF_CONST(b_const) DEF_CONST_##b_const
#define DEF_CONST_true const
#define DEF_CONST_false

Then,

/* OK */
DEF_CONST(true)  int x;  /* expands to const int x */
DEF_CONST(false) int y;  /* expands to int y */

/* NOT OK */
bool bSomeBool = true;       // technically not C :)
DEF_CONST(bSomeBool) int z;  /* error: preprocessor does not know the value
                                of bSomeBool */

Also, allowing for passing macro parameters to DEF_CONST itself (as correctly pointed out by GMan and others):

#define DEF_CONST2(b_const) DEF_CONST_##b_const
#define DEF_CONST(b_const) DEF_CONST2(b_const)
#define DEF_CONST_true const
#define DEF_CONST_false

#define b true
#define c false

/* OK */
DEF_CONST(b) int x;     /* expands to const int x */
DEF_CONST(c) int y;     /* expands to int y */
DEF_CONST(true) int z;  /* expands to const int z */

You may also consider the much simpler (though potentially less flexible):

#if b_const
# define DEF_CONST const
#else /*b_const*/
# define DEF_CONST
#endif /*b_const*/
Sign up to request clarification or add additional context in comments.

3 Comments

Typo in the above, just missed the edit mark. Should be #define DEF_CONST(b_const) CONCATENATE(DEF_CONST_, b_const).
Yup - token pasting or stringizing ('##' or '#') preprocessor operators almost always really need a level of indirection to work as desired: stackoverflow.com/questions/1767683/…
Possible to expand this so it takes parameter as one would use in x macro?
8

Doing it as a parametrised macro is a bit odd.

Just do something like this:

#ifdef USE_CONST
    #define MYCONST const
#else
    #define MYCONST
#endif

Then you can write code like this:

MYCONST int x = 1;
MYCONST char* foo = "bar";

and if you compile with USE_CONST defined (e.g., typically something -DUSE_CONST in the makefile or compiler options) then it will use the consts; otherwise it won't.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.