Search code examples
cstringmacrosc-preprocessorstring-concatenation

How to concat macros in C


I have a macro that displays the month from __DATE__ as a numeric value string literal:

#define MONTH (\
  __DATE__[2] == 'n' ? (__DATE__[1] == 'a' ? "01" : "06") \
: __DATE__[2] == 'b' ? "02" \
: __DATE__[2] == 'r' ? (__DATE__[0] == 'M' ? "03" : "04") \
: __DATE__[2] == 'y' ? "05" \
: __DATE__[2] == 'l' ? "07" \
: __DATE__[2] == 'g' ? "08" \
: __DATE__[2] == 'p' ? "09" \
: __DATE__[2] == 't' ? "10" \
: __DATE__[2] == 'v' ? "11" \
: "12")

This works fine and produces the month I'm looking for. printf("%s", MONTH);. However, I'm trying to add this to a larger group of macros and am having trouble:

#define MYMONTH "M" MONTH

should produce the string: M11 right now. But instead, it produces the following compiler error:

error: called object is not a function or function pointer
#define MYMONTH   "M" MONTH

I know you can combine string literals with a macro by appending them:

#define COMMA ","
#define EXCLA "!"
#define MYSTR "Hello" COMMA " world" EXCLA

But why won't it work when there is logic involved?


Solution

  • Macros are just a string copy done in preprocessing.

    If we copy your MONTH macro into MYMONTH we get:

    #define MYMONTH "M" (\
      __DATE__[2] == 'n' ? (__DATE__[1] == 'a' ? "01" : "06") \
    : __DATE__[2] == 'b' ? "02" \
    : __DATE__[2] == 'r' ? (__DATE__[0] == 'M' ? "03" : "04") \
    : __DATE__[2] == 'y' ? "05" \
    : __DATE__[2] == 'l' ? "07" \
    : __DATE__[2] == 'g' ? "08" \
    : __DATE__[2] == 'p' ? "09" \
    : __DATE__[2] == 't' ? "10" \
    : __DATE__[2] == 'v' ? "11" \
    : "12")
    

    Which to the compiler looks like you are trying "M"(<some string here>)