cmacrosc-preprocessorstringification

Stringify first level macro expansion C


Is it possible to stringify this C macro:

 #define GPIO_INT_PIN (GPIO_PORT_D|GPIO_PIN_IRQ_RISING|GPIO_PIN5)

using something like

 MY_STRINGFY(GPIO_INT_PIN) 

to get

"(GPIO_PORT_D|GPIO_PIN_IRQ_RISING|GPIO_PIN5)" ?


Solution

  • Yes it is possible. Read about stringizing in GCC cpp documentation.

     #define STRINGIFY(It) #It
     #define MY_STRINGIFY(It) STRINGIFY(It)
    

    I corrected my answer thanks to Wojtek Surowka's one

    then use MY_STRINGIFY(GPIO_PORT_D|GPIO_PIN_IRQ_RISING|GPIO_PIN5) which would work much better if you use an enum to define the constants, e.g.

    enum Gpio_stuff_en {
         GPIO_PORT_D=5,
         GPIO_PIN_IRQ_RISING=17,
         GPIO_PIN5=23
    };
    

    Of course that won't work as you want if you need GPIO_PORT_D to be a macro, .e.g. because it expands to some non-constant-literal expression (like a variable, or an access to a field of some global structure, etc....)

    As a counter-example:

    #define FOO 1
    #define BAR 2
    #define STRINGIFY(s) #s
    #define MY_STRINGIFY(s) STRINGIFY(s)
    
    MY_STRINGIFY(FOO|BAR)
    

    is expanded to "1|2" not to "FOO|BAR", if your remove the two #define-s for FOO and for BAR and replace them with

    enum {
      FOO=1,
      BAR=2 };
    

    you really get the expansion "FOO|BAR" as you want. Check with gcc -C -E ...

    Also:

    enum {FOO=1, BAR=2};
    #define FOOORBAR (FOO|BAR)
    #define STRINGIFY(s) #s
    #define MY_STRINGIFY(s) STRINGIFY(s)
    
    MY_STRINGIFY(FOOORBAR)
    

    is expanded as "(FOO|BAR)" . But if you use #define for FOO and for BAR you get the "(1|2)" expansion.

    Maybe you could add in your own header, after including the external header defining GPIO_PORT_D etc... as a literal constants, something like :

    enum {en_GPIO_PORT_D= GPIO_PORT_D,
          en_GPIO_PIN_IRQ_RISING= GPIO_PIN_IRQ_RISING,
          en_GPIO_PIN5= GPIO_PIN5};
    #undef GPIO_PORT_D
    #undef GPIO_PIN_IRQ_RISING 
    #undef GPIO_PIN5
    #define GPIO_PORT_D en_GPIO_PORT_D
    #define GPIO_PIN_IRQ_RISING en_GPIO_PIN_IRQ_RISING
    #define GPIO_PIN5 en_GPIO_PIN5
    

    and then you'll get more readable stringified constants (but not exactly what you dream of).