個人博客:www.shishangguan.net
宏定義分爲兩種:函數
1.變量式宏定義,如spa
#define abc def #define str "string" #define num 100
2.函數式宏定義,.net
#define device_init_wakeup(dev,val) \ do { \ device_can_wakeup(dev) = !!(val); \ device_set_wakeup_enable(dev,val); \ } while(0)
注意:多行的時候,須要用do{}while(0)包裝起來,這樣更像一個函數調用。同時注意帶有字增自減運算符的狀況。code
在函數式宏定義中, # 運算符用於建立字符串, # 運算符後面應該跟一個形參(中間能夠有空格
或Tab),例如:orm
#define STR(s) # s STR(hello world) //展開後爲"hello world",自動加雙引號。
注意:實參中的多個空格會被替換成一個空格。若是遊爽引號",會被自動添加轉義符,blog
## 運算符把先後兩個預處理Token鏈接成一個預處理Token,函數式宏定義和變量式宏定義均可以使用。遞歸
#define CONCAT(a, b) a##b CONCAT(con, cat) //展開後是concat #define HASH_HASH # ## # //展開後是##
函數式宏定義也可以使用可變參數,如字符串
#define showlist(...) printf(#__VA_ARGS__) #define report(test, ...) ((test)?printf(#test):\ printf(__VA_ARGS__)) showlist(The first, second, and third items.); report(x>y, "x is %d but y is %d", x, y);
替換後變成get
printf("The first, second, and third items."); ((x>y)?printf("x>y"): printf("x is %d but y is %d", x, y));
注意,__VA_ARGS__包含參數間的逗號。博客
還有一種gcc的擴展,如
#define DEBUGP(format, ...) printk(format, ## __VA_ARGS__)
,##放在這兒,若是可變參數部分爲空的時候,展開的時候第一個參數後不會有逗號。如
DEBUGP("info") //printk("info")
宏展開規則:
1.在展開當前宏函數時,若是形參有#(字符串化操做)或##(記號鏈接操做)則不進行宏參數的展開,不然先展開宏參數,再展開當前宏(就像先計算函數中的參數,而後調用函數同樣)。
2.宏展開不能遞歸展開。
個人博客:www.while0.com