2016-09-15 91 views
1

最近,我遇到了我的代碼奇怪的行爲:類似於C++對象包含宏URL解釋爲註釋

#define STR(X) #X 
#define XSTR(X) STR(X) 
#define TEST_SERVER_HTTP http://host.cz/import.php 
qDebug() << "Test server: " XSTR(TEST_SERVER_HTTP); 

輸出只是「HTTP:」文本。

我已經想通了,URL的「//」部分在這裏被解釋爲C++註釋,將其餘的URL文本切掉。

明顯的解決方法是

#define TEST_SERVER_HTTP http:\/\/host.cz\/import.php 

但是我得到(G ++)警告

invalid string literal, ignoring final '\' [enabled by default] 

何宏使用,即使編譯後的代碼運行正常。

的問題是:

  1. 有一些「正確」的方式在C++中如何引用斜線壓制註釋開始的雙斜槓意思?

  2. 是否有一些「規範」的解決方法將URL常量作爲替代對象類宏的值?

而且沒有

#define TEST_SERVER_HTTP "http://host.cz/import.php" 

不是在我的代碼的其餘部分給出的理由可以接受的。

+2

*「由於我的其他代碼中給出的原因,不能接受」*。哪個 ? – Jarod42

+0

恐怕這是無法完成的。兩個連續的斜線開始評論,兩個單獨的斜線不能重合。將它們並置會留下空間,並且不能粘貼它們,因爲'//不是有效的標記。 – Quentin

+0

如何定義字符串文字? – AndyG

回答

0

這很容易做到,但你需要破解進去(一如既往):

#define STRINGIFY_(x) #x 
#define STRINGIFY(x) STRINGIFY_(x) 
#define SLASH()/
#define DOUBLE_SLASH() SLASH()SLASH() 
#define STH_BEFORE() sth/before 
#define STH_AFTER() sth/after 
#define STH_DOUBLE_SLASH_STH STH_BEFORE()DOUBLE_SLASH()STH_AFTER() 

int main() 
{ 
    //test 
    std::cout << STRINGIFY(STH_DOUBLE_SLASH_STH) << std::endl; 
} 

輸出:

sth/before//sth/after 

可用新的宏觀非definiable版本將是:

#define PLACEBO(x) x 
#define STH_DOUBLE_SLASH_STH(x,y) PLACEBO(x)DOUBLE_SLASH()PLACEBO(y) 

int main() 
{ 
    std::cout << STRINGIFY(STH_DOUBLE_SLASH_STH(before, after)) << std::endl; 
} 

經MSVC 2015和GCC 5.3.0測試。


還要注意,MSVC允許這樣的註釋(這是不理智的!)

DOUBLE_SLASH() fun comment 
0

你無法逃避的C/C++代幣;唯一反斜槓有效的地方是字符串文字。除了字符串文字(並且不是通用字符名稱的一部分)之外,反斜槓只是一個單字符標記,僅在預處理階段纔有效。

然而,它很容易防止在代碼初始分割爲令牌期間形成多字符標記,並且您可以在不引入空白的情況下這樣做。所有你需要的是身份宏:

#define I(X) X 

現在你可以用它來避免雙斜線變得評論:

#define STR(X) #X 
#define XSTR(X) STR(X) 
#define TEST_SERVER_HTTP http:I(/)I(/)host.cz/import.php 
qDebug() << "Test server: " XSTR(TEST_SERVER_HTTP); 

有使用上的單斜線沒有點,或任何其他字符。

但是,該解決方案不會工作以逃避引號和撇號(或空白,就此而言)。據我所知,沒有辦法引入無與倫比的引用或撇號作爲標記。

聲明:我沒有嘗試使用MSVC,它已知有一個不兼容的預處理器實現。但是在任何符合標準的實施中,它都應該沒有問題。