Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use #if inside #define in the C preprocessor?

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 
like image 689
Wxy Avatar asked May 14 '10 05:05

Wxy


People also ask

How do we use a semicolon?

Use a semicolon to replace a period between related sentences when the second sentence starts with either a conjunctive adverb or a transitional expression, such as for example, for instance, that is, besides, accordingly, furthermore, otherwise, however, thus, therefore.

When should a semicolon be used examples?

A semicolon may be used between independent clauses joined by a connector, such as and, but, or, nor, etc., when one or more commas appear in the first clause. Example: When I finish here, and I will soon, I'll be glad to help you; and that is a promise I will keep.

How do you use commas and semicolons?

When a comma separates two complete sentences joined by a conjunction (and, but, or, nor, for, so, or yet) the comma and the conjunction can be replaced with a semicolon. I ate dinner, and I went to the movies. = I ate dinner; I went to the movies. She finished top of her class, but she was struggling to find work.

How do you use dashes correctly?

Use dashes to mark the beginning and end of a series, which might otherwise get confused, with the rest of the sentence: Example: The three female characters—the wife, the nun, and the jockey—are the incarnation of excellence. Dashes are also used to mark the interruption of a sentence in dialogue: Example: “Help!


2 Answers

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*/ 
like image 171
vladr Avatar answered Oct 06 '22 09:10

vladr


Doing it as a paramterised macro is a bit odd.

Why not 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.

Edit: Actually I see Vlad covered that option at the end of his answer, so +1 for him :)

like image 23
GrahamS Avatar answered Oct 06 '22 08:10

GrahamS