1、概念
#define命令是C語言中的一個宏定義命令,它用來將一個標識符定義爲一個字符串,該標識符被稱爲宏名,被定義的字符串稱爲替換文本。
該命令有兩種格式:一種是簡單的宏定義,另一種是帶參數的宏定義。
(1)
(2) 帶參數的宏定義
2、常見問題總結
爲了能清楚的理解問題,首先說一下C語言的編譯過程。c語言的編譯經過預處理、編譯、彙編、連接,而宏定義在預處理階段生成,此過程只是純粹的替換和展開沒有任何計算(這個是關鍵)。
(1)下面一段帶來,請寫出其輸出其結果
分析:展開是在預處理階段完成的,這個階段把替換文本只是看作一個字符串,並不會有任何的計算髮生,在展開時是在宏N出現的地方 只是簡單地使用串3+3來代替N,並不會增添任何的符號,所以對該程序展開後的結果是temp =3+3*3+3,計算後=15,這就是宏替換的實質
(3)帶參數的宏定義
#define
void main()
{
int
printf(“%d”,y);
}
按理說給的參數是2+2,所得的結果應該爲4*4=16,但是錯了,因爲該程序的實際結果爲8,仍然是沒能遵循純粹的簡單替換的規則,又是先計算再替換 了,在這道程序裏,2+2即爲area宏中的參數,應該由它來替換宏定義中的x,即替換成2+2*2+2=8了
#define FUN(a) "a"
則,輸入FUN(345)會被替換成什麼?
其實,如果這麼寫,無論宏的實參是什麼,都不會影響其被替換成"a"的命運。
也就是說,""內的字符不被當成形參,即使它和一模一樣。
那麼,你會問了,我要是想讓這裏輸入FUN(345)它就替換成"345"該怎麼實現呢?
請看下面關於#的用法
#define FUN(a) "a"
則,輸入FUN(345)會被替換成什麼?
其實,如果這麼寫,無論宏的實參是什麼,都不會影響其被替換成"a"的命運。
也就是說,""內的字符不被當成形參,即使它和一模一樣。
那麼,你會問了,我要是想讓這裏輸入FUN(345)它就替換成"345"該怎麼實現呢?
請看下面關於#的用法
3、 有參宏定義中#的用法
#define STR(str) #str
#用於把宏定義中的參數兩端加上字符串的""
比如,這裏STR(my#name)會被替換成"my#name"
一般由任意字符都可以做形參,但以下情況會出錯:
STR())這樣,編譯器不會把“)”當成STR()的參數。
STR(,)同上,編譯器不會把“,”當成STR的參數。
STR(A,B)如果實參過多,則編譯器會把多餘的參數捨去。(VC++2008爲例)
STR((A,B))會被解讀爲實參爲:(A,B),而不是被解讀爲兩個實參,第一個是(A第二個是B)。 #define FUN(a) "a"
則,輸入FUN(345)會被替換成什麼?
其實,如果這麼寫,無論宏的實參是什麼,都不會影響其被替換成"a"的命運。
也就是說,""內的字符不被當成形參,即使它和一模一樣。
那麼,你會問了,我要是想讓這裏輸入FUN(345)它就替換成"345"該怎麼實現呢?
請看下面關於#的用法
有參宏定義中#的用法
#define STR(str) #str
#用於把宏定義中的參數兩端加上字符串的""
比如,這裏STR(my#name)會被替換成"my#name"
一般由任意字符都可以做形參,但以下情況會出錯:
STR())這樣,編譯器不會把“)”當成STR()的參數。
STR(,)同上,編譯器不會把“,”當成STR的參數。
STR(A,B)如果實參過多,則編譯器會把多餘的參數捨去。(VC++2008爲例)
STR((A,B))會被解讀爲實參爲:(A,B),而不是被解讀爲兩個實參,第一個是(A第二個是B)。 有參宏定義中#的用法
#define STR(str) #str
#用於把宏定義中的參數兩端加上字符串的""
比如,這裏STR(my#name)會被替換成"my#name"
一般由任意字符都可以做形參,但以下情況會出錯:
STR())這樣,編譯器不會把“)”當成STR()的參數。
STR(,)同上,編譯器不會把“,”當成STR的參數。
STR(A,B)如果實參過多,則編譯器會把多餘的參數捨去。(VC++2008爲例)
STR((A,B))會被解讀爲實參爲:(A,B),而不是被解讀爲兩個實參,第一個是(A第二個是B)。
形式參數不能用帶引號的字符串替換。
但是,如果在替換文本中,參數名以#作爲前綴則結果將被擴展爲 由 實際參數 替換 此實際參數的帶引號的字符串。例如,可以將它與字符串連接運算結合起來編寫一個調試打印宏:
#define dprint(expr) printf(#expr “ = %\n”,expr)
使用語句 dprint(x/y);
調用宏時,該宏將被擴展爲:printf(“x/y”“ = %\n”,x/y);
其中的字符串被連接起來了,這樣便等價於printf(“x/y = %\n”,x/y);
在實際參數中,每個雙引號 “ 將被替換爲 \” ;反斜槓\將被替換爲\\,因此替換後的字符串是合法的字符串常量。
預處理運算符 ## 爲宏擴展提供了一種連接實際參數的手段。如果替換文本中的參數與 ## 相鄰,則該參數將被實際參數替換,##與前後的空白符將被刪除,並對替換後的結果重新掃描。
例如,下面定義的宏paste用於連接兩個參數
#define paste(front, back) front ## back
因此,宏調用past(name,1)的結果將建立記號name1.