I found this snippet on stackoverflow the other day (thanks for that):
#define PLATFORM 3
#define PASTER(x,y) x ## _ ## y
#define EVALUATOR(x,y) PASTER(x,y)
#define PLATFORMSPECIFIC(fun) EVALUATOR(fun, PLATFORM)
extern void PLATFORMSPECIFIC(somefunc)(char *x);
Compiled with gcc -E, it results in:
# 1 "xx.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "xx.c"
extern void somefunc_3(char *x);
However:
#define PLATFORM linux
#define PASTER(x,y) x ## _ ## y
#define EVALUATOR(x,y) PASTER(x,y)
#define PLATFORMSPECIFIC(fun) EVALUATOR(fun, PLATFORM)
extern void PLATFORMSPECIFIC(somefunc)(char *x);
results in:
# 1 "xx.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "xx.c"
extern void somefunc_1(char *x);
What can I do to make this return 'somefunc_linux' ?. Clang seems to do it right, btw.
This is called token pasting or token concatenation. The ' ## ' preprocessing operator performs token pasting. When a macro is expanded, the two tokens on either side of each ' ## ' operator are combined into a single token, which then replaces the ' ## ' and the two original tokens in the macro expansion.
The preprocessor outputs one make rule containing the object file name for that source file, a colon, and the names of all the included files, including those coming from -include or -imacros command-line options.
The double-number-sign or token-pasting operator (##), which is sometimes called the merging or combining operator, is used in both object-like and function-like macros. It permits separate tokens to be joined into a single token, and therefore, can't be the first or last token in the macro definition.
Preprocessing tokens (pp-tokens) are a superset of regular tokens. Preprocessing tokens allow the source file to contain non-token character sequences that constitute valid preprocessing tokens during translation. There are four categories of preprocessing tokens: Header filenames, meant to be taken as a single token.
If you want to use linux as a name, you can change your compiler options to undefine it:
gcc -Ulinux
or to be standards compliant:
gcc -std=c90 -pedantic ... # or -std=c89 or -ansi
gcc -std=c99 -pedantic
gcc -std=c11 -pedantic
See more discussion about why here: Why does the C preprocessor interpret the word "linux" as the constant "1"?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With