Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C language macro code - #define with 2 '##'

I recently came across this question and could not find supporting document or data in explanation. The question was asked to me and the person was not willing to share the answer.

#define BIT(A)       BIT_##A
#define PIN_0        0

"Do we get BIT_0 by using macro BIT(PIN_0)? If no make necessary corrections?"

I dont know the answer to the above question?

like image 756
madD7 Avatar asked Sep 15 '15 05:09

madD7


People also ask

What is a macro in C code?

The macro in C language is known as the piece of code which can be replaced by the macro value. The macro is defined with the help of #define preprocessor directive and the macro doesn't end with a semicolon(;). Macro is just a name given to certain values or expressions it doesn't point to any memory location.


1 Answers

The macro

#define BIT(A) BIT_##A

means to create a single token from what would otherwise be two separate tokens. Without using ## (the token concatenation operator), you might be tempted to do one of:

#define BIT(A) BIT_A
#define BIT(A) BIT_ A

The problem with the first is that, because BIT_A is already a single token, no attempt to match the A to the passed argument will succeed, and you'll get the literal expansion BIT_A no matter what you've used as an argument:

BIT(42) -> BIT_A

The problem with the second is that, even though A is a separate token and will therefore be subject to replacement, the final expansion will not be a single token:

BIT(42) -> BIT_ 42

The ## in your macro takes the value specified by A, and appends it to the literal BIT_ forming one token so, for example,

BIT(7)    -> BIT_7
BIT(PIN0) -> BIT_PIN0, but see below if you want BIT_0

This is covered in C11 6.10.3.3 The ## operator:

... each instance of a ## preprocessing token in the replacement list (not from an argument) is deleted and the preceding preprocessing token is concatenated with the following preprocessing token.

The resulting token is available for further macro replacement.


Now, if you want a macro that will concatenate together BIT_ and another already-evaluated macro into a single token, you have to use some trickery to get it to do the initial macro substitution before the concatenation.

That's because the standard states that the concatenation is performed before regular macro replacement, which is why this trickery is needed. The problem with what you have:

#define PIN_0  0
#define BIT(A) BIT_##A

is that the ## expansion of BIT(PIN0) will initially result in the single token BIT_PIN0. Now, although that's subject to further macro replacement, that single token doesn't actually have a macro replacement, so it's left as is.

To get around this, you have to use levels of indirection to coerce the preprocessor into doing regular macro replacement before ##:

#define CONCAT(x,y) x ## y
#define PIN0 0
#define BIT(A) CONCAT(BIT_,A)

This series of macros shown above goes through a number of stages:

BIT(PIN0)
-> CONCAT(BIT_,PIN0)
   -> CONCAT(BIT_,0)
      -> BIT_0
like image 150
paxdiablo Avatar answered Nov 15 '22 00:11

paxdiablo