Problem with C preprocessor in Microsoft Visual Studio 2010
I am facing a problem with new Visual C ++ in VS 2010.
I have a title with the following definitions:
#define STC(y) #y
#define STR(y) STC(\y)
#define NNN(y) 0##y
#define NUM(y) NNN(y)
The goal is that you can have some constant around like
#define TOKEN x5A
and then you can have the token as a number or string:
NUM(TOKEN) -> 0x5A
STR(TOKEN) -> "\x5A"
This is expected behavior according to macro argument substitution rules and has worked well with gcc, open watcom, pellesC (lcc), Digital Mars C and Visual C ++ in VS2008 Express so far.
Today I recompiled the library with VS2010 Express only to find that it no longer works! Using the newer version I would get:
NUM(TOKEN) -> 0x5A
STR(TOKEN) -> "\y"
It seems that the new preprocessor treats \y
as an escape sequence even within the body of a macro, which doesn't make sense since the escape sequences make sense in literal strings.
I suspect this is a gray area of ββthe ANSI standard, but even if the original behavior was sanctioned by the standard, MS VC ++ is not entirely known as 100% ANSI C, so I guess I'll have to live with the new MS compiler behavior.
Considering anyone has a suggestion on how to re-implement the original macro behavior using VS2010?
EDIT: Macro fixed NUM()
EDIT: Possible solution
I think I found a way to do this:
#define STC(y) #y
#if defined(_MSC_VER) && (_MSC_VER >= 1600)
#define STA(x,y) STC(x##y)
#define STR(y) STA(\,y)
#else
#define STR(y) STC(\y)
#endif
#define NNN(y) 0##y
#define NUM(y) NNN(y)
Now I am getting:
#define TOKEN x2E
NUM(TOKEN) -> 0x2E
STR(TOKEN) -> "\x2E"
Of course, gcc complains about attaching a backslash to the literal ( \ ## x2E
) because the result is not a valid preprocessor character, but MS seems happy, hence #ifdef
.
I'd love to hear if anyone has a better solution!
a source to share
You are / relying on some strange non-standard compiler behavior.
Your macro NUM
is not written correctly. It would never work in either the old or the new version of the compiler. When you do NUM(TOKEN)
, the result of expanding the macro in any standard compiler will be 0TOKEN
, not 0x5A
. For your macro to NUM
work as intended, you need to implement it in a two-tier way:
#define NUM_(y) 0##y
#define NUM(y) NUM_(y)
The only reason it has "worked" for you so far is because of another compiler glitch.
I'm not sure yet what is happening with the event STR
. The compiler is really complaining about an unrecognized escape sequence. There must be a compiler error.
a source to share
MSVC is not a C compiler, it is a C ++ compiler. The C compiler doesn't even offer some of the C99 features, nor is it intended to be competitive with a modern C compiler.
I will also question your use of the preprocessor in this way - it seems to me that it is a little more than OTT.
a source to share