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!

+2


a source to share


4 answers


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.

+5


a source


If you are using

#define STR(y) STC(\\y) 

      



then it works for me with VS2010.

+1


a source


I think this is the correct definition for STR (y). Worked in a test program under gcc and apparently used normal macro methods.

#define STC(y)      #y
#define STR(y)      "\\" STC(y)

      

+1


a source


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.

-five


a source







All Articles