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

I recently came across this issue and could not find a supporting document or data in the explanation. A question was asked of me, and the person did not want to share this answer.

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

"Do we get BIT_0 using the BIT macro (PIN_0)? If you do not make the necessary corrections?"

I do not know the answer to the above question?

+6
source share
1 answer

Macro

 #define BIT(A) BIT_##A 

means creating 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 the following:

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

The problem with the first is that, since BIT_A already a single token, no attempt to match A with the passed argument will fail, and you will get a literal extension of BIT_A regardless of what you used as the argument:

 BIT(42) -> BIT_A 

The problem with the second is that although A is a separate token and therefore will be replaced, the final extension will not be a single token:

 BIT(42) -> BIT_ 42 

## in your macro takes the value indicated by A and adds it to the literal BIT_ , forming one token, for example,

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

This is described in C11 6.10.3.3 The ## operator :

... each instance of the preprocessing token ## in the substitution list (not from the argument) is deleted and the previous preprocessing token is combined with the next preprocessing token.

The resulting token is available for further macro replacement.


Now, if you want the macro to combine BIT_ and another already-evaluated macro into one token, you should use some tricks to force it to perform the initial macro substitution before concatenation.

This is because the standard states that concatenation is performed before a regular macro replacement, so this trick is needed. The problem with what you have is:

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

the fact is that decomposition ## BIT(PIN0) will initially lead to a single token BIT_PIN0 . Now, although this is subject to further macro replacement, this single token does not actually have a macro replacement, so it remains as it is.

To get around this, you need to use indirection levels to force the preprocessor to perform the usual 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 several steps:

 BIT(PIN0) -> CONCAT(BIT_,PIN0) -> CONCAT(BIT_,0) -> BIT_0 
+10
source

All Articles