I've encountered a problem with the new Visual C++ in VS 2010.
I've got a header with the following defines:
#define STC(y) #y
#define STR(y) STC(\y)
#define NNN(y) 0##y
#define NUM(y) NNN(y)
The intent is that you can have some constant around like
#define TOKEN x5A
and then you can have the token as a number or as a string:
NUM(TOKEN) -> 0x5A
STR(TOKEN) -> "\x5A"
This is the expected behavior under the the substitution rules of macros arguments and so far it has worked well with gcc, open watcom, pellesC (lcc), Digital Mars C and Visual C++ in VS2008 Express.
Today I recompiled the library with VS2010 Express only to discover that it doesn't work anymore! Using the new version I would get:
NUM(TOKEN) -> 0x5A
STR(TOKEN) -> "\y"
It seems that the new preprocessor treats \y
as an escape sequence even within a macro body which is a non-sense as escape sequences only have a meaning in literal strings.
I suspect this is a gray area of the ANSI standard but even if the original behavior was mandated by the standard, MS VC++ is not exactly famous to be 100% ANSI C compliant so I guess I'll have to live with the new behavior of the MS compiler.
Given that, does anybody have a suggestion on how to re-implement the original macros behavior with VS2010?
EDIT: Corrected the NUM()
macro
EDIT: Possible solution
I think I've found a way to do it:
#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 get:
#define TOKEN x2E
NUM(TOKEN) -> 0x2E
STR(TOKEN) -> "\x2E"
Of course gcc complains about joining a backslash to a literal (\ ## x2E
) because the result is not a valid preprocessor symbol but MS seems happy, hence the #ifdef
.
I'll be happy to hear if anyone has a better solution!