【问题标题】:What's special about R and L in the C++ preprocessor?C++ 预处理器中的 R 和 L 有什么特别之处?
【发布时间】:2014-02-01 14:58:06
【问题描述】:

我通过 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

hello.i 包含:

#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?

【问题讨论】:

  • gccclang 似乎没有这样做,LR 是字符串文字前缀。看起来它正在应用 # 错误。
  • 不在 Visual Studio 2012 上重现。
  • 这个bug已经reported,微软无法重现这个bug。
  • @remyabel 可以复制here
  • The result for MS Visual C++ charizing operator 也很有趣。

标签: c++ visual-c++ c++11 c-preprocessor compiler-bug


【解决方案1】:

更新

看起来错误报告被标记为 this one 的副本,其中有一个更新:

已将针对此问题的修复程序签入编译器源代码。修复应该会出现在 Visual C++ 的下一个主要版本中。

原创

正如remyabel 指出的,这是reported buggccclang 都不会产生这个结果,而 stringizing operator # 根据 Visual Studios 文件,这些是以下替换(强调我的未来):

实际参数的第一个标记之前和实际参数的最后一个标记之后的空白将被忽略。实际参数中标记之间的任何空格都会减少为结果字符串文字中的单个空格。因此,如果注释出现在实际参数中的两个标记之间,它会减少为一个空格。生成的字符串字面量会自动与任何相邻的字符串字面量连接,它们之间仅用空格分隔。

此外,如果参数中包含的字符在字符串文字中使用时通常需要转义序列(例如,引号 (") 或反斜杠 () 字符),则会在字符之前自动插入必要的转义反斜杠.

它对应于C++ draft standard 部分16.3.2 # 运算符 它说:

如果在替换列表中,参数前面紧跟 # 预处理标记,则两者都被替换为单个字符串文字预处理标记,其中包含对应的预处理标记序列的拼写 争论。参数的预处理标记之间每次出现的空白都会成为字符串文字中的单个空格字符。删除第一个预处理标记之前和包含参数的最后一个预处理标记之后的空白。否则,参数中每个预处理标记的原始拼写将保留在字符串文字中,但产生字符串文字和字符文字的拼写的特殊处理除外:在字符文字的每个 " 和 \ 字符之前插入一个 \ 字符或字符串文字(包括分隔符 " 字符)。

RLC++11 的唯一关联是它们与 string literals 具有特殊含义,但我不明白这应该如何影响这一点案子。

看起来L\R\ 也会产生同样的问题。

他们确实记录了一个non-compliant issue,上面写着:

当#(字符串化)运算符与包含转义序列的字符串一起使用时,Visual C++ 的行为不正确。在这种情况下,编译器会产生 Compiler Error C2017。

不包括这种情况。

【讨论】:

  • EscapeSequences 的列表中没有简单的问号,但C++ Character Literals 的同一列表中有一个。
  • @Constructor 嗯,这很奇怪,我想知道他们是否真的意味着 ? 可以代表自己或 \? 这是标准所说的。
  • @Shafik 我猜它是用于三元组的,但这只是一个疯狂的猜测。
【解决方案2】:

这似乎是 MSVC 预处理器中的一个错误。好消息是,根据您对输出的挑剔程度,您可以通过在 R 或 L 之后放置一个空格来解决此问题。

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

【讨论】:

  • 不幸的是,对于我的情况,解决方法并不简单
猜你喜欢
  • 1970-01-01
  • 2012-09-28
  • 1970-01-01
  • 2011-03-21
  • 2011-04-18
  • 2017-02-19
  • 2016-09-30
相关资源
最近更新 更多