發信人: ax.bbs@bbs.ee.nthu.edu.tw.
(athena), 信區: test
標 題: 星星流講座 0039
發信站: ☆清華電機☆ (Thu Jul 13 19:31:40 1995)
轉信站: star
星星流講座 0039 C 語言教室
第 6 講 之 0 常數與定字
Topic: Constants and Literal
什麼叫做常數 (constant) 呢?相對於變數是可變動的資料而言,常數就是
不會變動的資料。例如圓周率π就是常見的數學常數。
定義常數的方法有兩種:
第一種方法是使用 #define 敘述,例如:
#define Pi 3.1415926
#define BELL '\007'
#define str "Hello, world\n"
我們前面提到過,以 # 開頭的命令叫做編譯指示 (compiler directives),
所以 #define 也是一種編譯指示。由我們上面的例子中可以看到常數不限任
何資料型態都可以是常數,你可以定義常數的數值、字元或字串。
第二種方法是使用 const 修飾子,例如:
const double Pi = 3.1415926;
const char BELL = '\007';
const char str[] = "Hello, world\n";
我們可以看到 str 這個字元陣列的元素數目並未給定,這是因為[1m若是 compiler
在編譯時就可以算出這個陣列的大小,那我們就可以省略陣列的元素個數。[0m
以 const 宣告的數,通常是在宣告時同時給定初值,之後所有對這個數的更
動均視為錯誤。
應用常數最常見的問題有三個:第一個是到底要用 #define 或是 const?
第二個是 const string (literal) 的設定,第三個是若是函數參數為常數
型態的指標又如何?
我們先來解決第一個問題:到底要用 #define 或是 const?
答案是用 const。為什麼?理由是因為使用 const 的話,compiler 才能
防止錯誤地使用常數。我們說過 #define 是一種編譯指示,而編譯指示是
以下圖的方式被處理的:
原始碼 (source code)
↓
+ - - - - - - - - - - - - - - +
| 前置處理程式 (preprocessor) |
| ↓ 擴張後的碼 |
| 編譯程式 (compiler) |
| ↓ |
| 最佳化程式 (optimizer) |
+ - - - - - - - - - - - - - - +
↓
中間碼 (intermediate code)
原始碼由前置處理程式處理之後,變成擴張後的碼 (expanded source),
然後才丟給 compiler 去編譯。前置處理程式是 cpp (C PreProcessor),
它也是由 gcc 偷偷地去呼叫的。前置處理程式會把所有的 #define 所產生
的常數直接代換進數值,也就是說像
printf ("%f\n", Pi);
這一行敘述,經過 cpp 處理之後就會變成
printf ("%f\n", 3.1415926);
這有什麼缺點呢?第一,cpp 並不會替你檢查型態是否正確。第二,compiler
根本看不到 Pi 這個符號 (因為被代換掉了),所以 compiler 產生出來的除
錯資料也沒有 Pi 這個符號,因此你若使用除錯器來替你的程式偵錯,也看不
到 Pi 這個符號,那意味著除錯變的非常地麻煩。所以盡量使用 const 來代
替 #define。
第二個和第三個問題,留待下講再敘。
--
本文原作者為徐振家,原作刊載於星星神教總壇 ☆清華電機☆ test 板。
你可以以電子文件的形式將本文自由流傳於台灣學術網路,但必須包含此版權聲明。
原作者依中華民國著作權法之規定,享有本文之著作權,請勿抄襲以免觸法。
未經授權任何人不得以任何形式對本文做任何修改及商業上之應用。
其他網路的轉載或其他用途的應用,請先知會作者,並取得其同意。
對本文有任何疑問或意見請 mail 給 ax.bbs@bbs.ee.nthu.edu.tw,謝謝。