C,C++宏中#与##的讲解
宏中的#的功能是將其后面的宏參數(shù)進行字符串化操作(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"的源文件名稱。因此要加一個中間轉(zhuǎn)換宏,先將__FILE__解析成"D:\XXX.cpp"字符串。
定義如下所示二個宏:
#define?_STRING(x)?#x
#define?STRING(x)?_STRING(x)
再調(diào)用下面語句將輸出帶""的源文件路徑
?????? 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;
再調(diào)用??paster(9);宏展開后token##n直接合并變成了token9。整個語句變成了
printf(?"token""9"" = %d", token9 );
在C語言中字符串中的二個相連的雙引號會被自動忽略,于是上句等同于
printf("token9 = %d", token9);。
即輸出token9 = 100
?
?
有了上面的基礎(chǔ)后再來看示例1
#define?WIDEN2(x) L?##?x
#define?WIDEN(x)?WIDEN2(x)
#define?__WFILE__?WIDEN(__FILE__)
wchar_t?*pwsz?=?__WFILE__;
第一個宏中的L是將ANSI字符串轉(zhuǎn)化成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?()也是用的這種技術(shù)。
在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默認(rèn)是ANSI編碼,因此要先設(shè)置成unicode編碼,在project菜單中選擇Setting,再在C/C++標(biāo)簽對話框中的Category中選擇Preprocessor。再地Preprocessor definitions編輯框中將_MBCS去掉,加上_UNICODE,UNICODE。轉(zhuǎn)載于:https://www.cnblogs.com/cyjsegull/p/4526296.html
總結(jié)
以上是生活随笔為你收集整理的C,C++宏中#与##的讲解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: openssl漏洞检查
- 下一篇: java8 lambda表达式实现自定义