2014-01-13 81 views
47

我通過Visual Studio 2013預處理器運行以下代碼。輸出令我驚訝。C++預處理器中的R和L有什麼特別之處?

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中的L和R有什麼特別之處?如果文件具有.c擴展名,則L和R與字母表的其餘部分相同。這與C++ 11有關嗎?它必須是一個新功能,因爲較早版本的MSVS不會以特殊方式使用L和R.

我該如何阻止MSVS 2013以這種特殊方式治療L和R?

+6

'gcc'和'clang'似乎沒有這樣做,'L'和'R'是字符串文字前綴。看起來它正在應用'#'錯誤。 –

+2

不在Visual Studio 2012上重現。 – selbie

+0

您可以在hello.cpp文件中顯示相關代碼嗎? –

回答

20

更新

貌似bug報告被標記爲this one的副本,其中有一個更新說:

此問題的修復程序已檢入到編譯器源中。該修補程序應顯示在Visual C++的下一個主要版本中。

原始

由於remyabel指出,這是一個reported bug。無論gcc也不clang產生這種結果和stringizing operator #根據Visual Studios文件,這些都是如下替換(重點煤礦前進):

白色空間中的實際參數的第一個標記之前和之後的最後一個令牌的實際論點被忽略。實際參數中的標記之間的任何空白區域都會縮減爲結果字符串文本中的單個空白區域。因此,如果在實際參數中的兩個標記之間發生評論,它將被縮減爲單個空白區域。生成的字符串文字會自動與任何相鄰的字符串文字連接起來,從中只用空格分隔。此外,如果參數中包含的字符在字符串文本中使用時(例如,引號(「)或反斜槓()字符)通常需要轉義序列,則必需的轉義反斜槓會自動插入字符。

其與C++ draft standard16.3.2#操作符它說相當於:

如果在替換列表,一個參數被立即由#預處理標記之前,兩者都通過一個替換單字符字符串文字預處理標記,其中包含相應的參數 的預處理標記序列的拼寫。參數的預處理標記之間每出現一個空白字符,都會成爲字符串文本中的單個空格字符。第一個預處理標記之前和包含參數的最後一個預處理標記之後的空白被刪除。否則,參數中每個預處理標記的原始拼寫保留在字符串文字中,除了用於生成字符串文字和字符文字拼寫的特殊處理外:在字符文字的每個「和\字符之前插入\字符或字符串文字(包括分隔的「字符)。

是涉及RL相對於C++ 11的唯一的事情是,他們有string literals特殊的含義,但我不認爲這應該是如何實現這種情況。

它也看起來像L\R\也產生相同的問題。

他們做文檔一個non-compliant issue和它說:當#(stringize)運算符與字符串包括轉義序列使用

的Visual C++不正確的行爲。在這種情況下,編譯器將生成編譯器錯誤C2017。

不包括這種情況。

+0

沒有在[EscapeSequences](http://msdn.microsoft.com/en-us/library/h21280bw.aspx)列表中有一個簡單問號,但在[C++字符文字](http:/ /msdn.microsoft.com/en-us/library/6aw8xdf2.aspx)。 – Constructor

+0

@Constructor嗯,這很奇怪,我想知道他們是否真的意味着'?'可以代表自己或通過'\?'這是標準所說的。 –

+2

@Shafik我在猜測它是用於三字母的,但這只是一個猜測。 – 2014-01-15 02:55:46

3

這似乎是MSVC預處理器中的一個錯誤。好消息是,這取決於你是多麼挑剔的你的輸出,你可以通過將一個空格後R或L.

解決此問題
A(L ?p:q), // "L ?p:q" 
+0

不幸的是,解決方法並不容易實現我的情況 – user52875