Can someone explain this to me?

I've seen this before but I still don't understand why you do it. Why did they need to double-define that DEBSHOW macro like that? I see their explanation and don't get it.

  #  define DEBPMACRO(x) DEBUG_SERIAL.println(F("D macro " #x " is " DEBSHOW(x)));

    // add a layer of indirection to allow macro extension
    #define DEBSHOW(x) DEBSHOW_(x)
    #define DEBSHOW_(x) #x

I can't really answer your question, other than to point out there are several rather arcane artifacts that go along with the manner and sequence in which pre-processor macros are parsed and expanded. It is (mostly) explained in the gcc pre-processor documentation, but will probably take a good bit of reading (and a bit of hair-pulling) to get to the answer you want.

FWIW - IIRC, #x creates a quoted string consisting of the string literal value of x. I have used this to create an array of strings from the members of an enum. For example, I believe if x evalutes to the literal string XYZZY, then #x will evaluate to the literal string "XYZZY", including the quotes.

Regards,
Ray L.

The comment confused you due to it being poorly written: not “extension” but “expansion”.

The two tier method allows the argument to undergo macro expansion before stringification. So:

#define FOO 123
DEBSHOW_(FOO) == “FOO”
DEBSHOW(FOO) == “123”

Delta_G:
Why did they need to double-define that DEBSHOW macro like that?

In this particular case I believe it is superfluous.

I tried some experiments and it looks like the expansion of DEBSHOW_(x) and DEBSHOW(x) are identical.

#define DEBUG_SERIAL Serial


#define DEBPMACRO(x) DEBUG_SERIAL.println(F("D macro " #x " is " DEBSHOW_(x) " which is " DEBSHOW(x) ));


// add a layer of indirection to allow macro extension
#define DEBSHOW(x) DEBSHOW_(x)
#define DEBSHOW_(x) #x


#define MACRO_1 1
#define MACRO_MACRO_1 MACRO_1
#define MACRO_2 (MACRO_1+MACRO_1)


const char array[] = "Test";


void setup()
{
  Serial.begin(115200);
  while (!Serial);


  DEBPMACRO(MACRO_1)
  DEBPMACRO(MACRO_MACRO_1)
  DEBPMACRO(MACRO_2)
  DEBPMACRO(array)
}


void loop() {}

Results:

D macro MACRO_1 is 1 which is 1
D macro MACRO_MACRO_1 is 1 which is 1
D macro MACRO_2 is (1+1) which is (1+1)
D macro array is array which is array

I suspect the entire point of the DEBSHOW() macro is to ensure only a FULLY expanded argument can get passed to the "#" operator in the DEBSHOW_() macro.

Try defining x as a string with spaces in it. My guess is the result may not be what you might expect.

Regards,
Ray L.

johnwasser:
I tried some experiments and it looks like the expansion of DEBSHOW_(x) and DEBSHOW(x) are identical.

You are forgetting that the DEBPMACRO itself is an additional layer of indirection.

Just print MACRO_MACRO_1 using both of DEBSHOW_* without using DEBPMACRO.

Yup. Superfluous...

#define MACROA 1 + 2 + 3 + a + x
#define MACROB MACROA + 42

#define DEBUG_SERIAL Serial
#  define DEBPMACRO(x) DEBUG_SERIAL.println(F("D macro " #x " is " DEBSHOW(x)));
// add a layer of indirection to allow macro extension
//#define DEBSHOW(x) DEBSHOW_(x)
//#define DEBSHOW_(x) #x
#define DEBSHOW(x) #x

void setup(void)
{
  Serial.begin( 250000 );
  DEBPMACRO(MACROA);
  DEBPMACRO(MACROB);
} 

void loop(void)
{
}
D macro MACROA is 1 + 2 + 3 + a + x
D macro MACROB is 1 + 2 + 3 + a + x + 42

Superfluous if you assume that the Delta_G's example is complete; but those are just 3 lines of code - there could be other lines where DEBSHOW() is used outside of an enclosing macro context.