[C] #Define 相關整理

Samuel Liu
4 min readSep 16, 2021

--

Define為C語言中在預處理階段對程式碼進行字串替換

  1. 最簡單的define定義

就是文本替換,例如

#define MAXTIME 1000

一個簡單的MAXTIME就定義好了,它代表1000,如果在程式裡面寫

if (i<MAXTIME){………}

編譯器在處理這個程式碼之前會對MAXTIME進行處理替換為1000。

2. define的函式定義

#define max(x,y) (x)>(y)?(x):(y)

這個定義就返回兩個數中較大的那個。看似與函數一樣,但由於define指是作文本替換,所以有可能會衍伸出原本沒有預期的錯誤。例如

#define Add(a,b) a+b

若在程式中使用 c*Add(a,b)*d,原先預期的做法是 c*(a+b)*d,但實際上是c*a+b*d,這樣就會造成結果不同而出錯。解決的辦法是加上一個括號

#define Add(a,b) (a+b)

這樣就考以符合我們的預期。

在一個常見的例子是用define 定義宣告,例如

#define PINT (int *)

然後在程式碼的區域宣告

PINT a, b;

原本預期是宣告兩個 int*,也就是int *a, *b,然而使用define只會變成int *a, b,b就只會是int。這個情況比較好的做法是使用typedef。

typedef int* PINT;

3. 字串operator

stringizing operator (#)

程式碼中插入字串,例如

#define C(x) #xC(1)------〉"1"

charizing operator (#@)

程式碼中插入字元,例如

#define B(x) #@xB(1)------〉'1'

以及最常用的Token-Pasting operator (##)

用以連接字串的操作符

#define A(x) Var_##xA(1)------〉Var_1

最後還有換行符號 (/)

若MACRO需多行時,用換行符號換行

#define MACRO(arg1, arg2) do { /
/* declarations */ /
stmt1; /
stmt2; /
/* ... */ /
} while (0) /* (no trailing ; ) */

4. 條件編譯

在大規模的開發過程中,特別是跨平台和系統的軟件裡,define最重要的功能是條件編譯。

#ifdef DV22_AUX_INPUT
#define AUX_MODE 3
#else
#define AUY_MODE 3
#endif
#ifndef XXX … ( #else ) … #endif

可以在編譯的時候通過#define設置編譯環境

很常見的還有避免標頭檔重複定義

#ifndef _NAME_H
#define _NAME_H
//標頭檔案內容
#endif

例如專案中的 student.h 檔案可以做如下修改:

#ifndef _STUDENT_H
#define _STUDENT_H
class Student {
//......
};
#endif

雖然該專案 main.cpp 檔案中仍 #include 了 2 次 “student.h”,但鑑於 _STUDENT_H 只能定義一次,所以 Student 類也僅會定義一次。再次執行該專案會發現,其可以正常執行。

其他關鍵字如下:

//定義巨集
#define [MacroName] [MacroValue]
//取消巨集
#undef [MacroName]
//普通巨集
#define PI (3.1415926)

帶參數的巨集
#define max(a,b) ((a)>(b)? (a),(b))

這裡有個連結介紹foreach語法糖怎麼來的,來達到以下減化的功用:

int arr[] = {10, 20, 30, 40, 50};
foreach(int *v, arr) {
printf("%d ", *v);
}

Reference:

https://icodding.blogspot.com/2018/05/c-define.html
https://www.ithome.com.tw/voice/136689
https://tw511.com/a/01/3191.html

--

--

Samuel Liu