先看下面三條語(yǔ)句:
#define Conn(x,y) x##y
#define ToChar(x) #@x
#define ToString(x) #x
1. ##
連接操作符
##
表示連接 ,x##y
表示什么谴餐?表示x
連接y
姻政,舉例說(shuō):
int n = Conn(123,456);
==> int n=123456;
char* str = Conn("asdf", "adf");
==> char* str = "asdfadf";
怎么樣,很神奇吧岂嗓!
需要注意的是汁展,##
的左右符號(hào)必須能夠組成一個(gè)有意義的符號(hào),否則預(yù)處理器會(huì)報(bào)錯(cuò)厌殉。
2. #@
字符化操作符
#@x
只能用于有傳入?yún)?shù)的宏定義中食绿,且必須置于宏定義體中的參數(shù)名前。作用是將傳的單字符參數(shù)名轉(zhuǎn)換成字符公罕,以一對(duì)單引用括起來(lái)其實(shí)就是給x
加上單引號(hào)器紧,結(jié)果返回是一個(gè)const char
。
舉例說(shuō):
char a = ToChar(1);
==> char a='1';
做個(gè)越界試驗(yàn)
char a = ToChar(123);
==> char a='3';
但是如果你的參數(shù)超過(guò)四個(gè)字符楼眷,編譯器就給給你報(bào)錯(cuò)了
铲汪!error C2015: too many characters in constant :P
3. #
字符串化操作符
#
表示字符串化操作符(stringification
)。其作用是:將宏定義中的傳入?yún)?shù)名轉(zhuǎn)換成用一對(duì)雙引號(hào)括起來(lái)參數(shù)名字符串罐柳。其只能用于有傳入?yún)?shù)的宏定義中掌腰,且必須置于宏定義體中的參數(shù)名前。說(shuō)白了硝清,他是給x
加雙引號(hào):
char* str = ToString(123132);
==> char* str="123132";
如果你想要對(duì)展開(kāi)后的宏參數(shù)進(jìn)行字符串化辅斟,則需要使用兩層宏。
#define xstr(s) str(s)
#define str(s) #s
#define foo 4
str (foo)
==> "foo"
xstr (foo)
==> xstr (4)
==> str (4)
==> "4"
s
參數(shù)在str
宏中被字符串化芦拿,所以它不是優(yōu)先被宏展開(kāi)士飒。然而s
參數(shù)是xstr
宏的一個(gè)普通參數(shù),在被傳遞到str
宏之前已經(jīng)被宏展開(kāi)蔗崎。
4. \
行繼續(xù)操作
\
行繼續(xù)操作當(dāng)定義的宏不能用一行表達(dá)完整時(shí)酵幕,可以用\
(反斜線)表示下一行繼續(xù)此宏的定義。
注意:最后一行不要加續(xù)行符啊.
VC的預(yù)處理器在編譯之前會(huì)自動(dòng)將\與換行回車(chē)去掉
(寫(xiě)成多行時(shí)缓苛,反斜杠后不能有空格芳撒,否則編譯器(ARM或VC)會(huì)報(bào)錯(cuò)!)未桥,這樣一來(lái)既不影響閱讀,又不影響邏輯,皆大歡喜.
5. VA_ARGS
__VA_ARGS__
宏用來(lái)接受不定數(shù)量的參數(shù)笔刹。例如:
#define eprintf(...) fprintf (stderr, __VA_ARGS__)
eprintf ("%s:%d: ", input_file, lineno)
==> fprintf (stderr, "%s:%d: ", input_file, lineno)
當(dāng)__VA_ARGS__
宏前面##
時(shí),可以省略參數(shù)輸入冬耿。
例如:
#define eprintf(format, ...) fprintf (stderr, format, ##__VA_ARGS__)
eprintf ("success!\n")
==> fprintf(stderr, "success!\n");