Reputation: 16724
I'm implementing The X macro, but I have a problem with a simple macro expansion. This macro (see below) is used into several macros usage examples, by including in this
article.
The compiler gives an error message, but I can see valid C code by using -E
flag with the GCC compiler.
The macro X-list is defined as the following:
#define LIST \
X(red, "red") \
X(blue, "blue") \
X(yellow, "yellow")
And then:
#define X(a, b) foo.##a = -1;
LIST;
#undef X
But the gcc given the following errors messages:
lixo.c:42:1: error: pasting "." and "red" does not give a valid preprocessing token
lixo.c:42:1: error: pasting "." and "blue" does not give a valid preprocessing token
lixo.c:42:1: error: pasting "." and "yellow" does not give a valid preprocessing token
Like I said, I can seen valid C code by using -E
switch on gcc:
lixo.c:42:1: error: pasting "." and "red" does not give a valid preprocessing token
lixo.c:42:1: error: pasting "." and "blue" does not give a valid preprocessing token
lixo.c:42:1: error: pasting "." and "yellow" does not give a valid preprocessing token
foo.red = -1; foo.blue = -1; foo.yellow = -1;;
What's a valid preprocessing token? Can someone explain this?
(before you say "why not just an either initialize or memset()
?" it's not my real code.)
Upvotes: 54
Views: 55335
Reputation: 1
In some circumstances this could be a solution:
Replace
#define X(a, b) foo.##a = -1;
by
#define X(a, b) foo.color_##a = -1;
The result (without warning or error) is:
foo.color_red = -1;
With this method the preprocessor concatenate token color_
with token red
. It is up to you to decide whether it’s acceptable to have color_red
instead of red
Note: you can replace the prefix color_
by any other valid variable name, including just _
Upvotes: 0
Reputation: 3203
Notably, the GCC documentation says your example should compile, albeit with a warning:
two tokens that don’t together form a valid token cannot be pasted together. For example, you cannot concatenate x with + in either order. If you try, the preprocessor issues a warning and emits the two tokens.
However, as you have noticed, invalid tokens in macros result in an error since GCC 4.3 (circa 2008).
Upvotes: 0
Reputation: 53037
.
separates tokens and so you can't use ##
as .red
is not a valid token. You would only use ##
if you were concatenating two tokens into a single one.
This works:
#define X(a, b) foo.a = -1;
What's a valid proprocessing token? Can someone explain this?
It is what gets parsed/lexed. foo.bar
would be parsed as 3 tokens (two identifiers and an operator): foo . bar
If you use ##
you would get only 2 tokens (one identifier and one invalid token): foo .bar
Upvotes: 66