C語言中,在宏里面使用’#’和’##’有它非常神奇的作用。在宏定義的替換的過程中,#號可以作為一個預處理運算符,把宏參數轉換為字符串。##運算符則可以把兩個宏參數組合在一起。下面就來說說具體的用法。
1、一般用法
我們使用#把宏參數變為一個字符串,用##把兩個宏參數貼合在一起。
下面的代碼是演示代碼:
#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; }
運行結果如下圖:
2016-03-21_171313
2、當宏參數是另一個宏的時候
需要注意的是:凡是宏定義里有用'#'或'##'的地方,宏參數是不會再展開。
(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)、當有'#'或'##'的時候
#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都不會再被展開,然而解決這個問題的方法也很簡單。加多一層中間轉換宏。加這層宏的用意是把所有宏的參數在這層里全部展開,那么在轉換宏里的那一個宏(_STR)就能得到正確的宏參數。
#include#include #defineA2 #define_STR(s)#s #defineSTR(s)_STR(s)//轉換宏 #define_CONS(a,b)(int)(a##e##b) #defineCONS(a,b)_CONS(a,b)//轉換宏 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) 然后再轉換成字符串。
第二個輸出代碼:
printf("CONS(A,A):%d ",CONS(A,A));
輸出為:CONS(A, A):200,CONS(A, A) ---> _CONS(2, 2) ---> int(2e2)。
3、'#'和'##'的一些應用特例
(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;;
對于宏的展開過程,每次只能解開當前層的宏,所以__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; }
當然了,上述的宏也可以獲取__DATE__,__LINE__等宏實際對應的值,上面專門定義了一個數組來存儲轉換后的值,實際使用時是否定義數組可自行安排。
審核編輯:湯梓紅
-
C語言
+關注
關注
180文章
7614瀏覽量
137712 -
字符串
+關注
關注
1文章
585瀏覽量
20601 -
代碼
+關注
關注
30文章
4825瀏覽量
69044 -
運算符
+關注
關注
0文章
172瀏覽量
11107
原文標題:C語言-#和##的神奇作用
文章出處:【微信號:嵌入式那些事,微信公眾號:嵌入式那些事】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
C語言typedef與#define的用法和區別
plsy指令具體用法
discrete filter 與discrete transfer 兩者的具體用法
C語言的位操作在STM32f1單片機編程的具體應用 精選資料推薦
STM32CUBEMX具體詳細的用法
C語言中的#和##的用法
![<b class='flag-5'>C</b><b class='flag-5'>語言</b>中的#和##的<b class='flag-5'>用法</b>](https://file.elecfans.com/web1/M00/D2/25/pIYBAF_IQOGAMwfiAAB5c0-AmmY227.png)
C語言中的typedef的用法
![<b class='flag-5'>C</b><b class='flag-5'>語言</b>中的typedef的<b class='flag-5'>用法</b>](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
評論