一、前言javascript
今天看代碼時候,遇到一些宏,以前沒有見過,感受挺新鮮。如是上網google一下,順便總結一下,方便之後學習和運用。C語言程序中普遍的使用宏定義,採用關鍵字define進行定義,宏只是一種簡單的字符串替換,根據是否帶參數分爲無參和帶參。宏的簡單應用很容易掌握,今天主要總結一下宏的特殊符號及慣用法。html
(1)宏中包含特殊符號:#、##.java
(2)宏定義用do{ }while(0)web
二、特殊符號#、##數組
(1)#性能
When you put a # before an argument in a preprocessor macro, the preprocessor turns that argument into a character array. 學習
在一個宏中的參數前面使用一個#,預處理器會把這個參數轉換爲一個字符數組 測試
簡化理解:#是「字符串化」的意思,出如今宏定義中的#是把跟在後面的參數轉換成一個字符串優化
#define ERROR_LOG(module) fprintf(stderr,"error: "#module"\n")
ERROR_LOG("add"); 轉換爲 fprintf(stderr,"error: "add"\n");ui
ERROR_LOG(devied =0); 轉換爲 fprintf(stderr,"error: devied=0\n");
(2)##
「##」是一種分隔鏈接方式,它的做用是先分隔,而後進行強制鏈接。
在普通的宏定義中,預處理器通常把空格解釋成分段標誌,對於每一段和前面比較,相同的就被替換。可是這樣作的結果是,被替換段之間存在一些空格。若是咱們不但願出現這些空格,就能夠經過添加一些##來替代空格。
1 #define TYPE1(type,name) type name_##type##_type 2 #define TYPE2(type,name) type name##_##type##_type
TYPE1(int, c); 轉換爲:int name_int_type ; (由於##號將後面分爲 name_ 、type 、 _type三組,替換後強制鏈接)
TYPE2(int, d);轉換爲: int d_int_type ; (由於##號將後面分爲 name、_、type 、_type四組,替換後強制鏈接)
三、宏定義中do{ }while(0)
第一眼看到這樣的宏時,以爲很是奇怪,爲何要用do……while(0)把宏定義的多條語句括起來?很是想知道這樣定義宏的好處是什麼,因而google、百度一下了。
採用這種方式是爲了防範在使用宏過程當中出現錯誤,主要有以下幾點:
(1)空的宏定義避免warning:
#define foo() do{}while(0)
(2)存在一個獨立的block,能夠用來進行變量定義,進行比較複雜的實現。
(3)若是出如今判斷語句事後的宏,這樣能夠保證做爲一個總體來是實現:
#define foo(x) \
action1(); \
action2();
在如下狀況下:
if(NULL == pPointer)
foo();
就會出現action1和action2不會同時被執行的狀況,而這顯然不是程序設計的目的。
(4)以上的第3種狀況用單獨的{}也能夠實現,可是爲何必定要一個do{}while(0)呢,看如下代碼:
#define switch(x,y) {int tmp; tmp="x";x=y;y=tmp;}
if(x>y)
switch(x,y);
else //error, parse error before else
otheraction();
在把宏引入代碼中,會多出一個分號,從而會報錯。這對這一點,能夠將if和else語句用{}括起來,能夠避免分號錯誤。
使用do{….}while(0) 把它包裹起來,成爲一個獨立的語法單元,從而不會與上下文發生混淆。同時由於絕大多數的編譯器都可以識別do{…}while(0)這種無用的循環並進行優化,因此使用這種方法也不會致使程序的性能下降
四、測試程序
簡單寫個測試程序,增強練習,熟悉一下宏的高級用法。
1 #include <stdio.h>
2 3 #define PRINT1(a,b) \ 4 { \ 5 printf("print a\n"); \ 6 printf("print b\n"); \ 7 } 8 9 #define PRINT2(a, b) \ 10 do{ \ 11 printf("print a\n"); \ 12 printf("print b\n"); \ 13 }while(0) 14 15 #define PRINT(a) \ 16 do{\ 17 printf("%s: %d\n",#a,a);\ 18 printf("%d: %d\n",a,a);\ 19 }while(0) 20 21 #define TYPE1(type,name) type name_##type##_type 22 #define TYPE2(type,name) type name##_##type##_type 23 24 #define ERROR_LOG(module) fprintf(stderr,"error: "#module"\n") 25 26 main() 27 { 28 int a = 20; 29 int b = 19; 30 TYPE1(int, c); 31 ERROR_LOG("add"); 32 name_int_type = a; 33 TYPE2(int, d); 34 d_int_type = a; 35 36 PRINT(a); 37 if (a > b) 38 { 39 PRINT1(a, b); 40 } 41 else 42 { 43 PRINT2(a, b); 44 } 45 return 0; 46 }
測試結果以下:
五、參考網址
http://blog.csdn.net/jiangjingui2011/article/details/6706967
http://www.kuqin.com/language/20080721/11906.html
http://www.360doc.com/content/12/0405/16/8302596_201146109.shtml