C++预处理器中的R和L有什么特殊之处?

47
我通过Visual Studio 2013预处理器运行了以下代码。输出结果让我感到惊讶。
hello.cpp的内容如下:
#define A(j) #j

A(A?)
A(B?)
A(C?)
A(D?)
A(E?)
A(F?)
A(G?)
A(H?)
A(I?)
A(J?)
A(K?)
A(L?)
A(M?)
A(N?)
A(O?)
A(P?)
A(Q?)
A(R?)
A(S?)
A(T?)
A(U?)
A(V?)
A(W?)
A(X?)
A(Y?)
A(Z?)

这个命令:

cl /P hello.cpp

你好。我包含以下内容:

#line 1 "hello.cpp"



"A?"
"B?"
"C?"
"D?"
"E?"
"F?"
"G?"
"H?"
"I?"
"J?"
"K?"
"L"
"M?"
"N?"
"O?"
"P?"
"Q?"
"R"
"S?"
"T?"
"U?"
"V?"
"W?"
"X?"
"Y?"
"Z?"

在尝试调用A(L?p:q)时,我遇到了这个问题,结果是"Lp:q",这对我来说不太好。

这是合适、定义清晰的C++吗?C++中的L和R有什么特殊之处?如果文件扩展名为.c,则L和R与其他字母相同。这与C++11有关吗?这一定是一个新特性,因为旧版本的MSVS不会特殊处理L和R。

我该怎么做才能阻止MSVS 2013以这种特殊方式处理L和R?


7
似乎gccclang没有这样做,LR是字符串字面量前缀。看起来它正在错误地应用# - Shafik Yaghmour
2
在Visual Studio 2012上无法重现。 - selbie
2
这个错误已经被报告,而微软无法重现这个错误。 - user1508519
7
@remyabel可以在这里进行复现(http://rextester.com/TDNLMZ57442)。 - Shafik Yaghmour
1
@Shafik 不用在意,我刚刚注意到这个错误报告是几天前发布的。当然微软还没有回复。 - user1508519
显示剩余5条评论
2个回答

20

更新

看起来这个错误报告已经被标记为这个的重复项,该重复项有一个更新,内容如下:

此问题的修复已经被纳入编译器源代码中。修复将在下一个主要版本的Visual C++中显示。

原文

正如remyabel指出的那样,这是一个报告的错误。无论是gcc还是clang都没有产生这种结果,而根据Visual Studios文档,字符串化运算符#有以下替换(接下来是我的强调):

实际参数的第一个令牌之前和最后一个令牌之后的空格将被忽略。实际参数中令牌之间的任何空格都将在生成的字符串字面值中缩减为单个空格。因此,如果注释出现在实际参数的两个令牌之间,则它将被缩减为单个空格。生成的字符串字面值将自动与任何相邻的字符串字面值连接起来,这些字符串字面值只由空格分隔。

此外,如果实参中包含的字符在使用字符串字面值时通常需要转义序列(例如引号(“)或反斜杠(\)字符),则必要的转义反斜杠会自动插入到该字符之前。

这对应于C++草案标准的第16.3.2#运算符

如果在替换列表中,一个参数紧随一个 # 预处理标记,则两者将被替换为单个字符字符串字面量预处理标记,其中包含相应参数的预处理标记序列的拼写。参数的每个预处理标记之间出现的空格在字符字符串字面量中变成单个空格字符。第一个预处理标记之前和组成参数的最后一个预处理标记之后的空格将被删除。否则,除了特殊处理生成字符串字面量和字符字面量的拼写外,保留参数中每个预处理标记的原始拼写:在字符字面量或字符串字面量(包括定界 " 字符)中,在每个 " 和 \ 字符之前插入一个 \ 字符。
唯一将 RLC++11 相关的是它们对 字符串字面量 有特殊含义,但我不知道这会如何影响此情况。
看起来 L\R\ 也产生了相同的问题。
他们确实记录了一个不符合规定的问题,并且它说:
Visual C++在使用包含转义序列的字符串时,#(字符串化)运算符不会正确地运行。在这种情况下,编译器将生成编译器错误C2017。
这并没有涵盖这种情况。

转义序列列表中没有简单的问号,但是在同一列表中的C++字符字面量中有一个。 - Constructor
@Constructor 嗯,这很奇怪,我想知道他们是真的意思是 ? 可以代表它自己还是 \?,这是标准所说的。 - Shafik Yaghmour
2
@Shafik 我猜测它是用于三字母符号,但这只是一个猜测。 - user1508519

3

这似乎是MSVC预处理器的一个漏洞。好消息是,根据您对输出的精细程度,您可以通过在R或L后面加上一个空格来解决此问题。

A(L ?p:q), // "L ?p:q"

不幸的是,对于我的情况,这种解决方法并不简单实现。 - user52875

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接