關於#和##
在C語言的宏中,#的功能是將其后面的宏參數進行字符串化操作(Stringfication),簡單說就是在對它所引用的宏變量通過替換后在其左右各加上一個雙引號。比如下面代碼中的宏:
1. #使用
#define WARN_IF(EXP) /
do{ if (EXP) /
fprintf(stderr, "Warning: " #EXP "/n"); } /
while(0)
那么實際使用中會出現下面所示的替換過程:
WARN_IF (divider ); 其中divider == 0
被替換為
do { if (divider == 0) fprintf(stderr, "Warning" "divider == 0" "/n"); } while(0);
這樣每次divider(除數)為0的時候便會在標准錯誤流上輸出一個提示信息。
2. ##使用
而## 被稱為連接符(concatenator),用來將兩個Token連接為一個Token。注意這里連接的對象是Token就行,而不一定是宏的變量。比如你要做一個菜單項命令名和函數指針組成的結構體的數組,並且希望在函數名和菜單項命令名之間有直觀的、名字上的關系。那么下面的代碼就非常實用:
struct command { char * name; void (*function) (void); };
#define COMMAND(NAME) { NAME, NAME ## _command } 此處的##表示后面有內容與NAME鏈接
// 然后你就用一些預先定義好的命令來方便的初始化一個command結構的數組了:
struct command commands[] = { COMMAND(quit), COMMAND(help), ... }
COMMAND宏在這里充當一個代碼生成器的作用,這樣可以在一定程度上減少代碼密度,間接地也可以減少不留心所造成的錯誤。我們還可以n個##符號連接 n+1個Token,這個特性也是#符號所不具備的。比如:
#define LINK_MULTIPLE(a,b,c,d) a##_##b##_##c##_##d //注意這里的規則(a##開頭,##d結束,中間都用##x##)
typedef struct _record_type LINK_MULTIPLE(name,company,position,salary);
// 這里這個語句將展開為:
// typedef struct _record_type name_company_position_salary;
個人認為##類似 運算符+ 起到連接的作用。
3 再看一個#使用如下:
#define display(name) printf(""#name"") int main() { display(name); }
運行結果是name,為什么不是"#name"呢?
---------------------------------------------------------------
#在這里是字符串化的意思
printf(""#name"") 相當於
printf("" "name" "")