C語言宏高級用法

C語言宏高級用法 [總結]

Reference:http://www.cnblogs.com/Anker/p/3418792.html

1、前言

    今天看代碼時候,遇到一些宏,之前沒有見過,感覺挺新鮮。如是上網google一下,順便總結一下,方便以後學習和運用。C語言程序中廣泛的 使用宏定義,採用關鍵字define進行定義,宏只是一種簡單的字符串替換,根據是否帶參數分爲無參和帶參。宏的簡單應用很容易掌握,今天主要總結一下宏 的特殊符號及慣用法。

 (1)宏中包含特殊符號:###.

      2)宏定義用do{ }while(0)

2、特殊符號###

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");

ERROR_LOG(devied =0); 轉換爲 fprintf(stderr,"error: devied=0\n");

2##

 “##”是一種分隔連接方式,它的作用是先分隔,然後進行強制連接。

  在普通的宏定義中,預處理器一般把空格解釋成分段標誌,對於每一段和前面比較,相同的就被替換。但是這樣做的結果是,被替換段之間存在一些空格。如果我們不希望出現這些空格,就可以通過添加一些##來替代空格。

1 #define TYPE1(type,name)   type name_##type##_type2 #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四組,替換後強制連接)

3、宏定義中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();
    就會出現action1action2不會同時被執行的情況,而這顯然不是程序設計的目的。
  (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();
在把宏引入代碼中,會多出一個分號,從而會報錯。這對這一點,可以將ifelse語句用{}括起來,可以避免分號錯誤。
  使用do{….}while(0) 把它包裹起來,成爲一個獨立的語法單元,從而不會與上下文發生混淆。同時因爲絕大多數的編譯器都能夠識別do{…}while(0)這種無用的循環並進行優化,所以使用這種方法也不會導致程序的性能降低

4、測試程序

  簡單寫個測試程序,加強練習,熟悉一下宏的高級用法。

 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##_type22 #define TYPE2(type,name)   type name##_##type##_type23 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     else42     {43     PRINT2(a, b);44     }45     return 0;46 }

測試結果如下:

5、參考網址

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

http://blog.csdn.net/liliangbao/article/details/4163440

發佈了49 篇原創文章 · 獲贊 16 · 訪問量 15萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章