巨集

我們已經知道,C 原始碼的檔頭部份, 可以崁入外部檔頭檔案 (#include)、定義符號常數 (#define)、宣告函式。 現在我們要示範,檔頭中還可以定義巨集 (macros)。 巨集可以說是符號常數的推廣。例如可以定義一個無參數的巨集

#define PI 4*atan(1)
則每當 C 編譯器在原始碼中讀到 PI 的時候, 就自動將它置換成 4*atan(1) 這個語句。 所以,我們在原始碼中看到的是 PI, 但可以想像,其實 C 看到的是 4*atan(1)

有趣的是,巨集可以帶有參數。 C 編譯器懂得如何代換。 例如,程式中如果經常需要將角度轉變成弧度, 而又不想為了這麼簡單的步驟寫一個函式來做。 可以定義一個巨集

#define RAD(x) x*atan(1)/45
如果在原始碼中寫
    sin(RAD(72))
可以想像,C 讀到的是 sin(72*atan(1)/45)。 因為 atan(1) 的結果是 double 型態, 所以整個 72*atan(1)/45 會以 double 型態做計算。 同理,如果在原始碼中寫
    sin(RAD(a[i]))
可以想像 C 讀到的是 sin(a[i]*atan(1)/45)

巨集的參數可以超過一個,例如

#define MAX(a,b) (a>b ? a : b)
右邊的那對括號未必需要,但是寫上去可以避免一些不必要的麻煩。 如果在原始碼中寫
    x = MAX(x, 3.5);
可以想像 C 讀到的是
    x = (x>3.5 ? x : 3.5);

最後,我們寫一個四捨五入 (round-off) 的巨集。 所謂四捨五入,是求一個實數的最靠近整數。 例如 round(3.14) 是 3,round(3.74) 是 4, round(-3.14) 是 -3,round(-3.74) 是 -4。 我們要避免呼叫外部函式,所以不用 floor()fabs() 這類的函式。做法是

#define ROUND(x) (int) (x>0 ? x+.5 : x-.5)

習題
  1. 寫一個代替 floor() 函式的巨集。
  2. 寫一個求兩數之間較小數的巨集 MIN(a,b)
  3. 寫一個以下格式的函式
    double round(double x, int n)
    
    回應 x 在 10n 位上做四捨五入得結果。 例如 round(3.14, -1) 應該回應 3, round(7862, 2) 應該回應 7900, round(2.71828, -3) 應該回應 2.72。

[ 前一節 ]‧[ 後一節 ]‧[ 回目錄 ]



注意:此處所有文件均為原著,個別的版權宣告日後會一一公布, 整體版面設計亦尚未完成。但仍請勿抄襲文字與圖片,以免觸犯著作權法。

Created: May 14, 2000
Last Revised: May 23, 2000
© Copyright 2000 Wei-Chang Shann 單維彰

shann@math.ncu.edu.tw