Microsoft Visual Studio 2010中的C预处理程序问题

Rem*_*o.D 2 c visual-studio-2010 visual-c++

我在VS 2010中遇到了新的Visual C++问题.

我有一个带有以下定义的标题:

#define STC(y) #y
#define STR(y) STC(\y)
#define NNN(y) 0##y
#define NUM(y) NNN(y)
Run Code Online (Sandbox Code Playgroud)

意图是你可以有一些常数

#define TOKEN x5A
Run Code Online (Sandbox Code Playgroud)

然后你可以将令牌作为数字或字符串:

NUM(TOKEN) -> 0x5A
STR(TOKEN) -> "\x5A"
Run Code Online (Sandbox Code Playgroud)

这是宏参数替换规则下的预期行为,到目前为止它在VS2008 Express中与gcc,open watcom,pellesC(lcc),Digital Mars C和Visual C++一起运行良好.

今天我用VS2010 Express重新编译了库,发现它不再起作用了!使用新版本我会得到:

NUM(TOKEN) -> 0x5A
STR(TOKEN) -> "\y"
Run Code Online (Sandbox Code Playgroud)

似乎新的预处理器\y甚至在宏体内处理为转义序列,这是无意义的,因为转义序列在文字字符串中只有意义.

我怀疑这是ANSI标准的灰色区域,但即使原始行为是由标准规定的,MS VC++也不是100%符合ANSI C标准,因此我想我将不得不忍受新的行为. MS编译器.

鉴于此,是否有人建议如何使用VS2010重新实现原始宏行为?

编辑:更正了NUM()

编辑:可能的解决方案

我想我已经找到了办法:

#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)
Run Code Online (Sandbox Code Playgroud)

现在我得到:

#define TOKEN x2E

NUM(TOKEN) -> 0x2E
STR(TOKEN) -> "\x2E"
Run Code Online (Sandbox Code Playgroud)

当然gcc抱怨加入一个反斜杠到literal(\ ## x2E)因为结果不是一个有效的预处理器符号,但MS似乎很高兴,因此#ifdef.

如果有人有更好的解决方案,我会很高兴听到!

AnT*_*AnT 5

您是/依赖于编译器的一些奇怪的非标准行为.

您的NUM宏写得不正确.它应该从来没有工作过,无论是在旧版本还是在新版本的编译器中.当您NUM(TOKEN)在任何符合标准的编译器中执行宏扩展的结果时,将是0TOKEN和不是0x5A.为了使NUM宏按预期工作,您必须以两级方式实现它:

#define NUM_(y) 0##y
#define NUM(y) NUM_(y)
Run Code Online (Sandbox Code Playgroud)

到目前为止它为你"工作"的唯一原因只是编译器中的另一个故障.

我不确定STR案件发生了什么.编译器确实抱怨无法识别的转义序列.必须是编译器中的错误.