巨集定義
預處理
預處理是程式編譯前的一個預先處理的動作,編譯一共有4個步驟:C原檔案 --> 預處理 --> 編譯 --> 彙編 -> 連結 --> 可執行檔案。
預處理的工作主要是展開我們C原始碼中的#開頭的語句,去掉了所有的註釋,在嚴格的意義來說,這些語句它並不屬於C語言的語法範疇。
以下是預處理的一些指令:
1.標頭檔案 : #include
2.巨集定義 : #define
3.取消巨集 : #undef
4.條件編譯 : #if \ #ifdef \ #ifndef \ #else \ #elif \ #enif
5.顯示錯誤 : #error
6.修改當前檔案的名字行號 :#line
7.向編譯器中傳送特定的指令 : #progma
可以在編譯程式的時候新增一個-E的選項,讓編譯器在預處理之後停下來不要繼續往下走,macro.i是源程式將#展開的內容。
gcc macro.c -o macro.i -E
巨集的概念
巨集(macro)實際上以一段字串,在原始碼中只是用來直接替換目標位置,一般巨集都使用全大寫字母(這只是一個習慣)。
#define PI 3.141592 #defineBUF_SIZE64 int main (int argc, char const *argv[]){ printf("PI:lf\t" , PI); int a = 100 + PI ; printf("a:%d\n", a); } 輸出:PI:3.141592 a:103
注意:
1.PI就是一個巨集,在我們的原始碼中如果出現巨集的使用,則通過預處理之後會直接被替換,只是直接的字元替換而已,不會考慮語法或運算關係。
無參巨集
無參巨集意味著我們在使用的時候不需要傳遞引數
#defineBUF_SIZE64
int main (int argc, char const *argv[]){
int arr[BUF_SIZE]; //定義了一個int型陣列,大小為64個
}
注意:
1.巨集他的本指就值直接的替換,沒有任何的語法檢查;
2.使用巨集的情況下如果程式碼有跟新迭代時,只需要修改巨集的一處,整個程式碼中所有用到巨集的地方都會被修改;
3.巨集的名字可以提高程式碼的可讀性。
帶參巨集
帶參巨集 在使用的時候需要攜帶引數來使用。
#define MAX(a,b) a>b ? a : b
int main (int argc, char const *argv[]){
printf("%d\t",MAX(100,998));
printf("%d\n",100>998?100:998);
}
輸出:998 998
注意:
1.使用帶參巨集的時候也是直接替換。
2.只是存粹的文字替換,沒有任何的語法檢查/判斷,也沒有任何的運算
3.巨集在預處理之後已經被替換,程式碼實際執行時是不需要額外的時間開銷,只會浪費一點記憶體的空間。
帶參巨集的副作用
由於巨集只是存粹的文字替換,中間不涉及任何的計算與語法檢查,型別匹配,所以用起來會比用函式麻煩很多。
#defineMAX(a,b)a>b?a:b
int main (int argc, char const *argv[]){
intx=100;
int y=200;
printf("MAX:%d\n",MAX(x,y==200?888:999));
從以上的程式碼中, 不管表示式 y==200?888:999 的值都是大於 x ,但是卻出來最大值為x 、
觀察一下替換後的結果:
printf("MAX:%d\n",x>y==200?888:999?x:y==200?888:999); //注意從右向左運算,?的優先順序大於:
所以應該修改長如下:
#defineMAX(a,b)(a)>(b)?(a):(b)
printf("MAX:%d\n",(x)>(y==200?888:999)?(x):(y==200?888:999));
使用括號對巨集當中的每一項括起來,提高優先順序,這樣替換之後邏輯不會出現問題。