C ++预处理器中的R和L有什么特别之处? [英] What's special about R and L in the C++ preprocessor?

查看:141
本文介绍了C ++预处理器中的R和L有什么特别之处?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我通过Visual Studio 2013预处理器运行以下代码。输出令我吃惊。



hello.cpp的内容:

  #define A(j)#j 

A(A?)
A(B?)
A(C?)
A $ b A(E?)
A(F?)
A(G?)
A(H?)
A ?)
A(K?)
A(L?)
A(M?)
A(N?)
A b A(P?)
A(Q?)
A(R?)
A(S?)
A )
A(V?)
A(W?)
A(X?)
A

命令:

  cl / P hello.cpp 

hello.i包含:

  #line 1hello.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和C中的L和R有什么特别之处?如果文件具有.c扩展名,则L和R被视为与字母表的其余部分相同。这是与C ++ 11相关吗?它必须是一个新功能,因为旧版本的MSVS不以特殊方式处理L和R.



我该如何阻止MSVS 2013以这种特殊方式处理L和R?

解决方案

更新



看起来错误报告被标记为这一个,其更新为:


已将此问题的修复程序检入编译器源。修复应显示在Visual C ++的下一个主要版本中。


原始 b
$ b

由于remyabel指出这是一个报告错误 gcc clang 都不会产生此结果和 Visual Studios 文档的en- us / library / 7e3a913x.aspxrel =nofollow>字符串化运算符#,这些是以下替换> > ): 实际参数被忽略。实际参数中的标记之间的任何空格都会减少到生成的字符串文本中的单个空格。因此,如果在实际参数中的两个令牌之间发生注释,则将其减少为单个空白空间。



此外,如果参数中包含的字符通常需要一个转义字符串,那么字符串字符串会自动与任何相邻的字符串字符串连接,当在字符串文字(例如,引号()或反斜杠()字符)中使用序列时,必需的转义反斜杠会自动插入字符之前。


这对应于 C ++草稿标准部分 16.3.2 #运算符其中说:


如果在替换列表中,参数前面紧跟着一个#预处理令牌,则这两个参数都将被单个字符串字面量预处理令牌替换,其中包含预处理令牌序列的拼写对应的
参数,参数的预处理标记之间的每个空格都会成为字符串文字中的一个空格字符。在第一预处理令牌之前和在包括该参数的最后预处理令牌之后的空白被删除。否则,参数中每个预处理令牌的原始拼写将保留在字符串文字中,除了用于生成字符串文字和字符文字拼写的特殊处理:\字符插入到字符串的每个和\字符之前字符文字或字符串文字(包括分隔符字符)。


唯一相关的 R L 相对于 C ++ 11 ,它们具有特殊含义,字符串字面量,但我不知道如何应该影响这种情况。



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



他们记录一个不合规问题,并说:


Visual C ++在#(stringize)运算符用于包含转义序列的字符串。在这种情况下,编译器将生成编译器错误C2017。


这不包括这种情况。


I ran the following code through the Visual Studio 2013 preprocessor. The output surprises me.

Contents of 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?)

The command:

cl /P hello.cpp

hello.i contains:

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

I ran into this while trying to call A(L?p:q), which resulted in "Lp:q" which is not good for me.

Is this proper, well-defined C++? What's special about L and R in C++? If the file has the .c extension, L and R are treated identical to the rest of the alphabet. Is this related to C++11? It must be a new feature, since older versions of MSVS don't tread L and R in a special way.

And what can I do to stop MSVS 2013 from treating L and R in this special way?

解决方案

Update

Looks like the bug report was marked as a duplicate of this one which has an update which says:

A fix for this issue has been checked into the compiler sources. The fix should show up in the next major release of Visual C++.

Original

As remyabel pointed out this is a reported bug. Neither gcc nor clang produce this results and the stringizing operator # according to Visual Studios documents, these are the following replacements (emphasis mine going forward):

White space preceding the first token of the actual argument and following the last token of the actual argument is ignored. Any white space between the tokens in the actual argument is reduced to a single white space in the resulting string literal. Thus, if a comment occurs between two tokens in the actual argument, it is reduced to a single white space. The resulting string literal is automatically concatenated with any adjacent string literals from which it is separated only by white space.

Further, if a character contained in the argument usually requires an escape sequence when used in a string literal (for example, the quotation mark (") or backslash () character), the necessary escape backslash is automatically inserted before the character.

which corresponds with the C++ draft standard section 16.3.2 The # operator which says:

If, in the replacement list, a parameter is immediately preceded by a # preprocessing token, both are replaced by a single character string literal preprocessing token that contains the spelling of the preprocessing token sequence for the corresponding argument. Each occurrence of white space between the argument’s preprocessing tokens becomes a single space character in the character string literal. White space before the first preprocessing token and after the last preprocessing token comprising the argument is deleted. Otherwise, the original spelling of each preprocessing token in the argument is retained in the character string literal, except for special handling for producing the spelling of string literals and character literals: a \ character is inserted before each " and \ character of a character literal or string literal (including the delimiting " characters).

The only thing that relates R and L with respect to C++11 is that they have special meaning with string literals but I don't see how that should effect this case.

It also looks like L\ and R\ also produce the same issue.

They do document one non-compliant issue and it says:

Visual C++ does not behave correctly when the # (stringize) operator is used with strings that include escape sequences. In this situation, the compiler will generate Compiler Error C2017.

which does not cover this case.

这篇关于C ++预处理器中的R和L有什么特别之处?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆