1. 程式人生 > 實用技巧 >巨集定義

巨集定義

預處理

 預處理是程式編譯前的一個預先處理的動作,編譯一共有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)); 

使用括號對巨集當中的每一項括起來,提高優先順序,這樣替換之後邏輯不會出現問題。