天天看點

C語言宏與單井号(#)和雙井号(##)        定義單行宏:主要有以下三種用法.

C(和C++)中的宏(Macro)屬于編譯器預處理的範疇,屬于編譯期概念(而非運作期概念)。下面對常遇到的宏的使用問題做了簡單總結。

關于#和##

在 C語言的宏中 ,#的功能是将其後面的宏參數進行字元串化操作(Stringfication),簡單說就是在對它所引用的宏變量通過替換後在其左右各加上一個雙引号。比如下面代碼中的宏:

#define WARN_IF(EXP) /

  do{ if (EXP) /

  fprintf(stderr, "Warning: " #EXP "/n"); } /

  while(0)

那麼實際使用中會出現下面所示的替換過程:

WARN_IF (divider == 0);

  被替換為

do {

  if (divider == 0)

  fprintf(stderr, "Warning" "divider == 0" "/n");

} while(0);

這樣每次divider(除數)為0的時候便會在标準錯誤流上輸出一個提示資訊。

      而##被稱為連接配接符(concatenator),用來将兩個Token連接配接為一個Token。注意這裡連接配接的對象是Token就行,而不一定是宏的變量。比如你要做一個菜單項指令名和函數指針組成的結構體的數組,并且希望在函數名和菜單項指令名之間有直覺的、名字上的關系。那麼下面的代碼就非常實用:

struct command

{

  char * name;

  void (*function) (void);

};

#define COMMAND(NAME) { NAME, NAME ## _command }

// 然後你就用一些預先定義好的指令來友善的初始化一個command結構的數組了:

struct command commands[] = {

  COMMAND(quit),

  COMMAND(help),

  ...

}

COMMAND宏在這裡充當一個代碼生成器的作用,這樣可以在一定程度上減少代碼密度,間接地也可以減少不留心所造成的錯誤。我們還可以n個##符号連接配接 n+1個Token,這個特性也是#符号所不具備的。比如:

#define LINK_MULTIPLE(a,b,c,d) a##_##b##_##c##_##d

typedef struct _record_type LINK_MULTIPLE(name,company,position,salary);

// 這裡這個語句将展開為:

// typedef struct _record_type name_company_position_salary;

      ## 連接配接符号由兩個井号組成,其功能是在帶參數的宏定義中将兩個子串(token)聯接起來,進而形成一個新的子串。但它不可以是第一個或者最後一個子串。所謂的子串(token)就是指編譯器能夠識别的最小文法單元。

     #符是把傳遞過來的參數當成字元串進行替代。

      下面來看看它們是怎樣工作的。這是MSDN上的一個例子。 假設程式中已經定義了這樣一個帶參數的宏:

         #define paster( n ) printf( "token" #n " = %d", token##n )

           同時又定義了一個整形變量: int token9 = 9;

          現在在主程式中以下面的方式調用這個宏: paster( 9 );

         那麼在編譯時,上面的這句話被擴充為: printf( "token" "9" " = %d", token9 );

        注意到在這個例子中,paster(9);中的這個”9”被原封不動的當成了一個字元串,與”token”連接配接在了一起,進而成為了token9。而#n也被”9”所替代。 可想而知,上面程式運作的結果就是在螢幕上列印出token9=9

        定義單行宏:主要有以下三種用法.

   1) 前加##或後加##,将标記作為一個合法的辨別符的一部分.注意,不是字元串.多用于多行的宏定義中.例如:

       #define A(x)  T_##x 則 int A(1) = 10; //等效于int T_1 = 10;

    2) 前加#@,将标記轉換為相應的字元,注意:僅對單一标記轉換有效

        #define B(x) #@x  則B(a)即’a’,B(1)即’1’.但B(abc)卻不甚有效.

   3) 前加#,将标記轉換為字元串.

 #define C(x) #x  則C(1+1) 即 ”1+1”.