I would be surprised if any compilers break if we use ## and #. However, using TOSTR or # directly is supposed to mean different things, and most often you want to use TOSTR.
Here is a simple demonstration program:
#include <stdio.h>
#define MY_FAVORITE_COLOR black #define TOSTR(x) # x #define GREETING_1(COLOR) "Hello, lover of " # COLOR #define GREETING_2(COLOR) "Hello, lover of " TOSTR(COLOR)
int main() { puts(GREETING_1(MY_FAVORITE_COLOR)); puts(GREETING_2(MY_FAVORITE_COLOR)); }
Leaving aside the question of whether black is a color or not, this will print:
Hello, lover of MY_FAVORITE_COLOR Hello, lover of black
This is because the argument of # (and ##) is not subject to macro expansion. But, as the example above show, you normally want macro expansion to occur, so you have to add a helper macro (TOSTR and PIKE_CONCAT).
But in the case of GET_VAL, where we use true and false as arguments, we don't want to macro-expand them. At least not when <stdbool.h> is included. And we never need to expand them -- there is no need to support something convoluted like:
#define TRUTH_VALUE false GET_VAL(TRUTH_VALUE) #undef TRUTH_VALUE
#define TRUTH_VALUE true GET_VAL(TRUTH_VALUE) #undef TRUTH_VALUE
(We are trying to use jemalloc with Pike, and for some reason including the jemalloc header file also seems to include <stdbool.h>, so we ran into this issue.)