【转】C,C++宏中#与##的讲解
轉自:C,C++宏中#與##的講解 - MoreWindows - 博客園
?文中__FILE__與示例1可以參見《使用ANSI C and Microsoft C++中常用的預定義宏》
宏中的#的功能是將其后面的宏參數進行字符串化操作(Stringizing operator),簡單說就是在它引用的宏變量的左右各加上一個雙引號。
如定義好#define?STRING(x)?#x之后,下面二條語句就等價。
???????char *pChar?=?"hello";
???????char *pChar?=?STRING(hello);
還有一個#@是加單引號(Charizing Operator)
#define?makechar(x)??#@x
???????char?ch?=?makechar(b);與char?ch?=?'b';等價。
但有小問題要注意,宏中遇到#或##時就不會再展開宏中嵌套的宏了。什么意思了?比如使用char *pChar?=?STRING(__FILE__);雖然__FILE__本身也是一個宏,但編譯器不會展開它,所以pChar將指向"__FILE__"而不是你要想的形如"D:\XXX.cpp"的源文件名稱。因此要加一個中間轉換宏,先將__FILE__解析成"D:\XXX.cpp"字符串。
定義如下所示二個宏:
#define?_STRING(x)?#x
#define?STRING(x)?_STRING(x)
再調用下面語句將輸出帶""的源文件路徑
???????char*?pChar?=?STRING(__FILE__);
???????printf("%s %s\n",?pChar, __FILE__);
可以比較下STRING(__FILE__)與__FILE__的不同,前將帶雙引號,后一個沒有雙引號。
再講下##的功能,它可以拼接符號(Token-pasting operator)。
MSDN上有個例子:
#define?paster(?n?)?printf(?"token"#n" = %d\n", token##n?)
int?token9?= 100;
再調用??paster(9);宏展開后token##n直接合并變成了token9。整個語句變成了
printf(?"token""9"" = %d", token9 );
在C語言中字符串中的二個相連的雙引號會被自動忽略,于是上句等同于
printf("token9 = %d", token9);。
即輸出token9 = 100
有了上面的基礎后再來看示例1
#define?WIDEN2(x) L?##?x
#define?WIDEN(x)?WIDEN2(x)
#define?__WFILE__?WIDEN(__FILE__)
wchar_t?*pwsz?=?__WFILE__;
第一個宏中的L是將ANSI字符串轉化成unicode字符串。如:wchar_t?*pStr?= L"hello";
再來看wchar_t?*pwsz?=?__WFILE__;
__WFILE__被首先展開成WIDEN(__FILE__),再展開成WIDEN2("__FILE__表示的字符串"),再拼接成?L"__FILE__表示的字符串"?即L"D:\XXX.cpp"?從而得到unicode字符串并取字符串地址賦值給pwsz指針。
在VC中_T(),TEXT?()也是用的這種技術。
在tchar.h頭文件中可以找到:
#define?_T(x)???????__T(x)
#define?__T(x)??????L?##?x
在winnt.h頭文件中可以找到
#define?TEXT(quote)?__TEXT(quote)???// r_winnt
#define?__TEXT(quote) L##quote??????// r_winnt
因此不難理解為什么第三條語句會出錯error C2065: 'LszText' : undeclared identifier
???????wprintf(TEXT("%s %s\n"),?_T("hello"),?TEXT("hello"));
???????char?szText[] =?"hello";
???????wprintf(TEXT("%s %s\n"),?_T(szText),?TEXT(szText));
而將"hello"定義成宏后就能正確運行。
#define?SZTEXT?"hello"
???????wprintf(TEXT("%s %s\n"),?_T(SZTEXT),?TEXT(SZTEXT));
注:由于VC6.0默認是ANSI編碼,因此要先設置成unicode編碼,在project菜單中選擇Setting,再在C/C++標簽對話框中的Category中選擇Preprocessor。再地Preprocessor definitions編輯框中將_MBCS去掉,加上_UNICODE,UNICODE。?
更多內容可以查考MSDN上對Preprocessor Operators的講解。
轉載請標明出處,原文地址:C,C++宏中#與##的講解 - MoreWindows - 博客園
?
總結
以上是生活随笔為你收集整理的【转】C,C++宏中#与##的讲解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【转】C++中#include包含头文件
- 下一篇: 特斯拉Model 3国产强敌 比亚迪海豹