views:

635

answers:

3

Hello,

I'm having a macro like this ( not exactly, but function is quite equivalent):

#define STRUCTMEMBER(Member,Value) GlobalStructInstance. ## Member = Value
...
STRUCTMEMBER(Item,1);

This works perfectly in Visual C++, but gcc 3.4.5 (MingGW) yield the following error:

pasting "." and "Item" does not give a valid preprocessing token

This also happens when I use the "->" operator. I didn't found hints on concatenation, that the usage of these operators is forbidden.

Does anyone have an idea ?

Best regards, Dinsdale

+5  A: 

Maybe Visual C++ is pasting a couple of spaces together to make another space. Not that whitespaces are tokens, but it would allow your code to work.

object.member is not a token, it's three tokens, so you don't need token-pasting to implement the macro you describe. Just remove the '##' and it should work everywhere.

[Edit: just checked, and the result of using ## to form something that isn't a valid token is undefined. So GCC is allowed to reject it and MSVC is allowed to ignore it and perform no paste, as far as I can tell.]

Steve Jessop
Thanks, I don't know why, but when I've tried it first this way it didn't worked...because of this I tried the ## operator... looks quite better now!
dinsdale
+4  A: 

From the gcc c preprocessor docs:

However, two tokens that don't together form a valid token cannot be pasted together.

structure.member is not a single token.

In this case you do not need to use the ## (token concatenation) operator. You can just remove it. Here is an example tested with gcc 4.2.4 on linux:

#include <stdio.h>

#define STRUCTMEMBER(Member, Value) GlobalStructInstance.Member = Value

struct {
    const char* member1;
}GlobalStructInstance;

int main(void)
{

    STRUCTMEMBER(member1, "Hello!");

    printf("GlobalStructInstance.member1 = %s\n",
           GlobalStructInstance.member1);

    return 0;
}
Karl Voigtland
+3  A: 

According to the C Standard, the result of the '##' preprocessing operator must be a 'preprocessing token' or the result is undefined (C99 6.10.3.3(3) - The ## operator).

The list of preprocessing tokens is (C99 6.4(3) - Lexical elements):

header names, identifiers, preprocessing numbers, character constants, string literals, punctuators, and single non-white-space characters that do not lexically match the other preprocessing token categories.

GCC lets you know that you're entering undefined territory. MSVC is silently happy with the undefined result (that is what you'd pretty much expect to happen).

Note that if you're not creating a single token anyway, then you don't need the token pasting operator. Generally (I'm sure there's probably an exception or two), 2 tokens separated by whitespace is equivalent to 2 tokens not separated by whitespace - as in your example.

Michael Burr