How to concatenate twice with the C preprocessor and expand a macro as in “arg ## _ ## MACRO”?

前端 未结 3 1655
轮回少年
轮回少年 2020-11-21 10:03

I am trying to write a program where the names of some functions are dependent on the value of a certain macro variable with a macro like this:

#define VARIA         


        
3条回答
  •  日久生厌
    2020-11-21 10:55

    Plain-English explanation of the EVALUATOR two-step pattern

    I haven't fully understood every word of the C standard, but I think this is a reasonable working model for how the solution shown in https://stackoverflow.com/a/1489985/895245 works, explained a little more verbosely. Let me know if my understanding is incorrect, hopefully with a minimal example that breaks my theory.

    For our purposes, we can think of macro expansion as happening in three steps:

    1. (prescan) Macro arguments are replaced:
      • if they are part of concatenation or stringification, they are replaced exactly as the string given on the macro call, without being expanded
      • otherwise, they are first fully expanded, and only then replaced
    2. Stringification and concatenation happen
    3. All defined macros are expanded

    Step-by-step example without indirection

    main.c

    #define CAT(x) pref_ ## x
    #define Y a
    
    CAT(Y)
    

    and expand it with:

    gcc -E main.c
    

    we get:

    pref_Y
    

    because:

    Step 1: Y is a the macro argument of CAT.

    x appears in a stringification pref_ ## x. Therefore, Y gets pasted as is without expansion giving:

    pref_ ## Y
    

    Step 2: concatenation happens and we are left with:

    pref_Y
    

    Step 3: any further macro replacement happens. But pref_Y is not any known macro, so it is left alone.

    We can confirm this theory by actually adding a definition to pref_Y:

    #define CAT(x) pref_ ## x
    #define Y a
    #define pref_Y asdf
    
    CAT(Y)
    

    and now the result would be:

    asdf
    

    because on Step 3 above pref_Y is not defined as a macro, and therefore expands.

    Step-by-step example with indirection

    If we use the two step pattern however:

    #define CAT2(x) pref_ ## x
    #define CAT(x) CAT2(x)
    #define Y a
    
    CAT(Y)
    

    we get:

    pref_a
    

    Step 1: CAT is evaluated. The argument x of CAT at CAT2(x) does not appear in a stringification. Therefore, Y is fully expanded before being replaced, going through steps 1, 2, and 3, which we omit here because it trivially expands to a. So we put a in CAT2(x) giving:

    CAT2(a)
    

    Step 2: there is no stringification to be done

    Step 3: expand all existing macros. We have the macro CAT2(a) and so we go on to expand that.

    Step 3.1: the argument x of CAT2 appears in a stringification pref_ ## x. Therefore, paste the input string a as is, giving:

    pref_ ## a
    

    Step 3.2: stringify:

    pref_a
    

    Step 3: expand any further macros. pref_a is not any macro, so we are done.

    GCC argument prescan documentation

    GCC's documentation on the matter is also worth a read: https://gcc.gnu.org/onlinedocs/cpp/Argument-Prescan.html

    Bunus: how those rules prevent nested calls from going infinite

    Now consider:

    #define f(x) (x + 1)
    
    f(f(a))
    

    which expands to:

    ((a + 1) + 1)
    

    instead of going infinite.

    Let's break it down:

    Step 1: the outer f is called with argument x = f(a).

    In the definition of f, the argument x is not part of a concatenation in the definition (x + 1) of f. Therefore it is first fully expanded before being replaced.

    Step 1.1.: we fully expand the argument x = f(1) according to steps 1, 2, and 3, giving x = (a + 1).

    Now back in Step 1, we take that fully expanded x argument equaling (a + 1), and put it inside the definition of f giving:

    ((a + 1) + 1)
    

    Steps 2 and 3: not much happens, because we have no stringification and no more macros to expand.

提交回复
热议问题