這行是什麼意思?特別是,##
是什麼意思?#define中的##是什麼意思?
#define ANALYZE(variable, flag) ((Something.##variable) & (flag))
編輯:
一點點困惑依然。沒有##
,結果如何?
這行是什麼意思?特別是,##
是什麼意思?#define中的##是什麼意思?
#define ANALYZE(variable, flag) ((Something.##variable) & (flag))
編輯:
一點點困惑依然。沒有##
,結果如何?
A little bit confused still. What will the result be without ##?
通常你不會注意到任何區別。但是是的區別。假設Something
的類型是:
struct X { int x; };
X Something;
而且看:
int X::*p = &X::x;
ANALYZE(x, flag)
ANALYZE(*p, flag)
沒有令牌連接符##
,它擴展爲:
#define ANALYZE(variable, flag) ((Something.variable) & (flag))
((Something. x) & (flag))
((Something. *p) & (flag)) // . and * are not concatenated to one token. syntax error!
隨着令牌級聯它擴展爲:
#define ANALYZE(variable, flag) ((Something.##variable) & (flag))
((Something.x) & (flag))
((Something.*p) & (flag)) // .* is a newly generated token, now it works!
請務必記住,預處理器在預處理令牌上操作,而不是上的文本。所以如果你想連接兩個令牌,你必須明確地說出來。
根據維基百科
Token concatenation, also called token pasting, is one of the most subtle — and easy to abuse — features of the C macro preprocessor. Two arguments can be 'glued' together using ## preprocessor operator; this allows two tokens to be concatenated in the preprocessed code. This can be used to construct elaborate macros which act like a crude version of C++ templates.
一個非常重要的部分是,此令牌級聯如下一些非常特殊的規則:
例如IBM doc:
實例是也非常自我說明
#define ArgArg(x, y) x##y
#define ArgText(x) x##TEXT
#define TextArg(x) TEXT##x
#define TextText TEXT##text
#define Jitter 1
#define bug 2
#define Jitterbug 3
隨着輸出:
ArgArg(lady, bug) "ladybug"
ArgText(con) "conTEXT"
TextArg(book) "TEXTbook"
TextText "TEXTtext"
ArgArg(Jitter, bug) 3
Source是IBM文檔。可能因其他編譯器而異。
要在行:
它加到變量屬性的 「東西」。並且接受一個邏輯上結合的變量,如果Something.variable有一個標誌設置,那麼這個變量會給出結果。
所以我最後的評論和你的問題(可編譯使用g ++)的例子:
// this one fails with a compiler error
// #define ANALYZE1(variable, flag) ((Something.##variable) & (flag))
// this one will address Something.a (struct)
#define ANALYZE2(variable, flag) ((Something.variable) & (flag))
// this one will be Somethinga (global)
#define ANALYZE3(variable, flag) ((Something##variable) & (flag))
#include <iostream>
using namespace std;
struct something{
int a;
};
int Somethinga = 0;
int main()
{
something Something;
Something.a = 1;
if (ANALYZE2(a,1))
cout << "Something.a is 1" << endl;
if (!ANALYZE3(a,1))
cout << "Somethinga is 0" << endl;
return 1;
};
讓我們考慮一個不同的例子:
考慮
#define MYMACRO(x,y) x##y
沒有##
,明確預處理器無法看到x
和y
作爲單獨的令牌,可以嗎?
在你的榜樣,
#define ANALYZE(variable, flag) ((Something.##variable) & (flag))
##
根本就沒有必要因爲你沒有做任何新的標識符。事實上,編譯器問題「錯誤:粘貼」。「」和「變量」不提供有效的預處理令牌「
這不是您的問題的答案,只是一個CW帖子,有一些技巧可以幫助您探索預處理器你自己。
預處理步驟實際上是在編譯任何實際代碼之前執行的。換句話說,當編譯器開始構建代碼時,沒有任何#define語句或類似的東西被留下。
瞭解預處理程序對代碼做什麼的一個好方法是獲取預處理輸出並查看它。
這是如何做到這一點的Windows:
創建一個名爲TEST.CPP一個簡單的文件,並把它放在一個文件夾中,比如C:\ TEMP。 礦看起來像這樣:
#define dog_suffix(variable_name) variable_name##dog
int main()
{
int dog_suffix(my_int) = 0;
char dog_suffix(my_char) = 'a';
return 0;
}
不是很有用,但很簡單。打開Visual Studio命令提示符下,導航到該文件夾,然後運行命令行如下:
c:\temp>cl test.cpp /P
所以,這是你的運行器(cl.exe),用你的文件編譯器,和/ P選項告訴編譯器將預處理輸出存儲到文件中。
現在在test.cpp旁邊的文件夾中,您會發現測試。我,這對我來說是這樣的:
#line 1 "test.cpp"
int main()
{
int my_intdog = 0;
char my_chardog = 'a';
return 0;
}
正如你所看到的,沒有的#define左側,只有它的代碼擴展成。
另請參閱:http://stackoverflow.com/questions/1597007/creating-c-macro-with-and-line-token-concatenation-with-positioning-macro – sharkin