1. 程式人生 > 實用技巧 >C語言學習筆記_C語言巨集定義與預處理

C語言學習筆記_C語言巨集定義與預處理

C語言學習筆記_C語言巨集定義與預處理

由原始碼到可執行程式的過程

  1. 原始碼;
  2. 預處理過的.i原始檔
  3. 彙編檔案.s
  4. 目標檔案.o
  5. elf可執行程式

條件編譯

// 定義XXX
#define XXX

// 這種方式直接判定XXX是否被定義
#ifdef XXX
#else
#endif

// 這種方式判斷條件是否為真
#if (1)
#else
#endif

巨集定義

巨集定義在編譯器的預處理階段會被直接替換;

替換的過程是遞迴的,如下:

#define N 10
#define M N

// 相當於int a[10];
int a[M];

當巨集定義帶引數的時候,擅用括號,避免替換的時候出現歧義,如獲取最大值的巨集:

#define MAX(a, b)	((a) > (b) ? (a) : (b))

int max(int a, int b) {
    return a>b?a:b;
}

int a = 1, b = 2;
int max = MAX(a*3, b);

這裡例子可能舉得不是很好,但是在某些時候不加括號會使得替換後引起歧義,導致出錯;

帶參巨集和帶參函式有如下差別:

  1. 巨集定義原地展開,因此沒有呼叫開銷;而函式是跳轉執行在返回;
  2. 巨集定義不會檢查引數的型別,返回值也不會附帶型別,而函式有明確的引數型別和返回值型別;當呼叫函式時編譯器會做引數的靜態型別檢查;

另外一個例子,利用巨集定義得到一年有多少秒:

#define SER_PER_YEAR	(365*24*60*60UL)

注意:

在程式中的數字預設為int型別,而秒數正好超過了int的範圍;

所以在數字後面加上UL使得陣列變成無符號long;

另外一個例子,利用條件巨集設定debug

// 定義DEBUG
#define DEBUG

// 使用undef消除對DEBUG的定義
#undef DEBUG

#ifdef DEBUG
#define debug(x) printf(x)
#else
#define debug(x)
#endif


debug("hello world.\n");

通過定義DEBUG,使得debug可以用於列印資訊,如果不需要了可以註釋DEBUG的定義,或者使用undef,使得消除除錯資訊更方便。

使用undef時,前面若沒有定義過,將會無視此語句;

行內函數

在巨集定義中講到,帶參巨集和函式的區別是:帶參巨集開銷小但是不做型別檢查,函式有呼叫開銷但是會做型別檢查;

而內斂函式具有上述兩者的優點,其沒有呼叫開銷且會做型別檢查,只需要在函式前加inline

inline void printInfo() {
	printf("hello world.\n");
}