發信人: 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 這個字元陣列的元素數目並未給定,這是因為若是 compiler
在編譯時就可以算出這個陣列的大小,那我們就可以省略陣列的元素個數。
以 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,謝謝。