C語言中,在宏里面使用’#’和’##’有它非常神奇的作用。在宏定義的替換的過程中,#號可以作為一個預(yù)處理運(yùn)算符,把宏參數(shù)轉(zhuǎn)換為字符串。##運(yùn)算符則可以把兩個宏參數(shù)組合在一起。下面就來說說具體的用法。
1、一般用法
我們使用#把宏參數(shù)變?yōu)橐粋€字符串,用##把兩個宏參數(shù)貼合在一起。
下面的代碼是演示代碼:
#include#defineSTRING(s)#s #defineCONNECT(a,b)(int)(a##e##b) intmain(void) { //輸出字符串"abcdefg" printf("string:%s ",STRING(abcdefg)); //2e3輸出:2000 printf("connect:%d ",CONNECT(2,3)); return0; }
運(yùn)行結(jié)果如下圖:
2016-03-21_171313
2、當(dāng)宏參數(shù)是另一個宏的時候
需要注意的是:凡是宏定義里有用'#'或'##'的地方,宏參數(shù)是不會再展開。
(1)、非’#’和’##’的情況
#include#defineTOW(2) #defineMUL(a,b)(a*b) intmain(void) { printf("%d*%d=%d ",TOW,TOW,MUL(TOW,TOW)); return0; }
上面代碼中打印那行的宏會被展開為:
printf("%d*%d=%d ",(2),(2),((2)*(2)));
(2)、當(dāng)有'#'或'##'的時候
#include#include #defineA(2) #defineSTR(s)#s #defineCONS(a,b)(int)(a##e##b) intmain(void) { //INT_MAX這行會被展開為:printf("intmax:%s ","INT_MAX"); printf("intmax:%s ",STR(INT_MAX)); //這一行會被展開為:printf("%s ",(int)(AeA)); printf("%s ",CONS(A,A)); return0; }
上面的代碼在編譯時會失敗,INT_MAX和A都不會再被展開,然而解決這個問題的方法也很簡單。加多一層中間轉(zhuǎn)換宏。加這層宏的用意是把所有宏的參數(shù)在這層里全部展開,那么在轉(zhuǎn)換宏里的那一個宏(_STR)就能得到正確的宏參數(shù)。
#include#include #defineA2 #define_STR(s)#s #defineSTR(s)_STR(s)//轉(zhuǎn)換宏 #define_CONS(a,b)(int)(a##e##b) #defineCONS(a,b)_CONS(a,b)//轉(zhuǎn)換宏 intmain(void) { //INT_MAX,int型的最大值,為一個變量 printf("intmax:%s ",STR(INT_MAX)); printf("CONS(A,A):%d ",CONS(A,A)); return0; }
其中代碼:
printf("intmax:%s ",STR(INT_MAX));
輸出為:int max: 2147483647,STR(INT_MAX) ---> _STR(2147483647) 然后再轉(zhuǎn)換成字符串。
第二個輸出代碼:
printf("CONS(A,A):%d ",CONS(A,A));
輸出為:CONS(A, A):200,CONS(A, A) ---> _CONS(2, 2) ---> int(2e2)。
3、'#'和'##'的一些應(yīng)用特例
(1)、合并匿名變量名
#include#define___ANONYMOUS1(type,var,line)typevar##line #define__ANONYMOUS0(type,line)___ANONYMOUS1(type,_anonymous,line) #defineANONYMOUS(type)__ANONYMOUS0(type,__LINE__) intmain(void) { ANONYMOUS(staticint); _anonymous9=666; printf("_anonymous9:%d ",_anonymous9); return0; }
上述代碼:ANONYMOUS(static int);最終展開為:static int _anonymous9; // 9表示該行行號;,下面分析下具體的展開過程:
第一次展開:ANONYMOUS(static int); ---> __ANONYMOUS0(static int, __LINE__);;
第二次展開:__ANONYMOUS0(static int, __LINE__); ---> ___ANONYMOUS1(static int, _anonymous, 9);;
第三次展開:___ANONYMOUS1(static int, _anonymous, 9); ---> static int _anonymous9;;
對于宏的展開過程,每次只能解開當(dāng)前層的宏,所以__LINE__在第二層才能被解開。
(2)、獲取文件名
#include#define_GET_FILENAME(filename)#filename #defineGET_FILENAME(filename)_GET_FILENAME(filename) intmain(void) { charfilename[]=GET_FILENAME(__FILE__); printf("filename:%s ",filename); return0; }
當(dāng)然了,上述的宏也可以獲取__DATE__,__LINE__等宏實(shí)際對應(yīng)的值,上面專門定義了一個數(shù)組來存儲轉(zhuǎn)換后的值,實(shí)際使用時是否定義數(shù)組可自行安排。
審核編輯:湯梓紅
-
C語言
+關(guān)注
關(guān)注
180文章
7594瀏覽量
135858 -
字符串
+關(guān)注
關(guān)注
1文章
575瀏覽量
20468 -
代碼
+關(guān)注
關(guān)注
30文章
4722瀏覽量
68231 -
運(yùn)算符
+關(guān)注
關(guān)注
0文章
170瀏覽量
11049
原文標(biāo)題:C語言-#和##的神奇作用
文章出處:【微信號:嵌入式那些事,微信公眾號:嵌入式那些事】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論