無參巨集定義:(即巨集名後不帶引數。)
其定義的一般形式為:
#define 識別符號 字串
其中各個名稱的含義如下:
1>其中的「#」表示這是一條預處理命令。凡是以「#」開頭的均為預處理命令。
2>「define」為巨集定義命令。
3>「識別符號」為所定義的巨集名。
4>「字串」可以是常數、表示式、格式串等。
例如:
#define m (a+b)
它的作用是指定識別符號m來代替表示式(a+b)。在編寫源程式時,所有的(a+b)都可由m代替,而對源程式作編譯時,將先由預處理程式進行巨集代換,即用(a+b)表示式去置換所有的巨集名m,然後再進行編譯。
程式1:
#define m (a+b)
main()
上例程式中首先進行巨集定義,定義m來替代表示式(a+b),在 s= m * m 中作了巨集呼叫。在預處理時經巨集展開後該語句變為:
s=(a+b)*(a+b)
但要注意的是,在巨集定義中表示式(a+b)兩邊的括號不能少。否則會發生錯誤。
如當作以下定義後:
#difine m (a)+(b)
在巨集展開時將得到下述語句:
s= (a)+(b)*(a)+(b)
1>巨集定義是用巨集名來表示乙個字串,在巨集展開時又以該字串取代巨集名,這只是一種簡單的代換,字串中可以含任何字元,可以是常數,也可以是表示式,預處理程式對它不作任何檢查。如有錯誤,只能在編譯已被巨集展開後的源程式時發現。
2>巨集定義不是說明或語句,在行末不必加分號,如加上分號則連分號也一起置換。
3>巨集定義必須寫在函式之外,其作用域為巨集定義命令起到源程式結束。
4>如要終止其作用域可使用:
#undef命令
帶參巨集定義:(即允許巨集帶有引數)
a.在巨集定義中的引數稱為形式引數,在巨集呼叫中的引數稱為實際引數。
b.對帶引數的巨集,在呼叫中,不僅要巨集展開,而且要用實參去代換形參。
帶參巨集定義的一般形式為:
#define 巨集名(形參表) 字串(在字串中含有各個形參)
例如:
#define m(y) ((y)*(y)+
3*(y)) /*巨集定義*/
....
k=m(5); /*巨集呼叫*/
....
在巨集呼叫時,用實參5去代替形參y,經預處理巨集展開後的語句為:
k=5
*5+3
*5
程式2:
#define max(a,b) (a>b)?a:b
main()
上例程式的第一行進行帶參巨集定義,用巨集名max表示條件表示式:
(a>b)?a
:b
形參a,b均出現在條件表示式中。
程式第七行
max
=max(x,y)
為巨集呼叫,實參x,y,將代換形參a,b。
巨集展開後該語句為:
max=(x>y)?x
:y;
用於計算x,y中的大數。
注:
a.防止重複定義#define條件編譯
b.標頭檔案(.h)可以被標頭檔案或c檔案包含;
c.重複包含(重複定義)
d.由於標頭檔案包含可以巢狀,那麼c檔案就有可能包含多次同乙個標頭檔案,就可能出現重複定義的問題的。 通過條件編譯開關來避免重複包含(重複定義)
例如:
#ifndef __headerfile***__
#define __headerfile***__
„ 檔案內容
„
#endif
在簡單巨集定義的使用中,當替換文字所表示的字串為乙個表示式時,容易引起誤解和誤用。
例如:
#define n 2+2
void main()
(1) 出現問題:
在此程式中存在著巨集定義命令,巨集n代表的字串是2+2,在程式中有對巨集n的使用,一般同學在讀該程式時,容易產生的問題是先求解n為2+2=4,然後在程式中計算a時使用乘法,即n*n=4*4=16,其實該題的結果為8,為什麼結果有這麼大的偏差?
(2) 問題解析:
如1節所述,巨集展開是在預處理階段完成的,這個階段把替換文字只是看作乙個字串,並不會有任何的計算發生,在展開時是在巨集n出現的地方 只是簡單地使用串2+2來代替n,並不會增添任何的符號,所以對該程式展開後的結果是a=2+2*2+2,計算後=8,這就是巨集替換的實質,如何寫程式才能完成結果為16的運算呢?
(3)解決辦法:
/*將巨集定義寫成如下形式*/
#define n (2+2)
/*這樣就可替換成(2+2)*(2+2)=16*/
在帶引數的巨集定義的使用中,極易引起誤解。例如我們需要做個巨集替換能求任何數的平方,這就需要使用引數,以便在程式中用實際引數來替換巨集定義中的引數。
一般學生容易寫成如下形式:
#define area(x) x*x
/*這在使用中是很容易出現問題的,看如下的程式*/
void main()
(1) 問題解析:
按理說給的引數是2+2,所得的結果應該為4*4=16,但是錯了,因為該程式的實際結果為8,仍然是沒能遵循純粹的簡單替換的規則,又是先計算再替換 了,在這道程式裡,2+2即為area巨集中的引數,應該由它來替換巨集定義中的x,即替換成2+2*2+2=8了。
那如果遵循(1)中的解決辦法,把2+2 括起來,即把巨集體中的x括起來,是否可以呢?#define area(x) (x)(x),對於area(2+2),替換為(2+2)(2+2)=16,可以解決,但是對於area(2+2)/area(2+2)又會怎麼樣呢,有的學生一看到這道題馬上給出結果,因為分子分母一樣,又錯了,還是忘了遵循先替換再計算的規則了,這道題替換後會變為 (2+2)(2+2)/(2+2)(2+2)即4*4/4*4按照乘除運算規則,結果為16/4*4=4*4=16,那應該怎麼呢?
(2)解決方法:
在整個巨集體上再加乙個括號,即#define area(x) ((x)*(x)),不要覺得這沒必要,沒有它,是不行的。
要想能夠真正使用好巨集定義,一定要先將程式中對巨集的使用全部替換成它所代表的字串,完全展開後再進行相應的計算,就不會寫錯執行結果。如果是自己程式設計使用巨集替換,則在使用簡單巨集定義時,當字串中不只乙個符號時,加上括號表現出優先順序,如果是帶引數的巨集定義,則要給巨集體中的每個引數加上括號,並在整個巨集體上再加乙個括號。看到這裡,不禁要問,用巨集定義這麼麻煩,這麼容易出錯,可不可以摒棄它, 那讓我們來看一下在c語言中用巨集定義的好處吧。
例如:
#include
#define product(x) x*x
int main()
依次輸出結果:
j=9;i=5;k=49;i=7
C語言學習總結
1 c語言中有乙個賦值表示式,是其他多數高階語言中沒有的。2 c 語言的輸入與輸出操作是由函式來完成的,它不提供輸入輸出語句。3 c語言中有乙個共用體,其變數所點記憶體長度是其最長 成員變數的長度。4 static char a language char p a 8 5 void main int...
C語言學習總結
看了李明杰老師的c 語言課程,感覺老師講得很細 很透。收穫了很多新的知識,對cc 語言課程的學習總結。1.執行c 語言程式的步驟 1 編寫 c原始檔 2 編譯 c原始檔為 o目標檔案 3 鏈結 o目標檔案為可執行檔案 4 執行可執行檔案 2.常用格式符 1 d i 整數 int 2 f 小數 flo...
C語言學習總結
while語句 當條件為真時,進行迴圈。for迴圈,第二個條件為真時,執行迴圈體 對於單鏈表應該設定的變數l的型別為結構指標型別,初始化時就是把l變成頭指標,並且還為其分配了記憶體空間 巨集定義 define long string it represent a long string that i...