眾所周知,C語言一開始只有#define,C程序員用#define定義符號常量。但后來ANSI C加入了const限定符,而const應該比#define更好,為什么現在的C程序員還在大量使用#define來定義常量呢?
這並不是我沒有根據地亂說的。這樣的例子有很多,例如<limits.h>,例如Windows API,例如OpenGL……
<limits.h>是C標准頭文件,發明C語言的人難道不知道const嗎?
Windows是Microsoft開發的,難道Microsoft的代碼很差勁?
開發OpenGL的難道寫的代碼也很爛嗎?
太奇怪了吧!因此,肯定是有什么特殊原因讓他們使用#define……
曾今我在百度上用中文查這個問題,發現根本查不到;昨天我Google了“why use #define instead of const”,才在stackoverflow上找到了一個同樣的問題:
Why do most C developers use define instead of const?
於是我閱讀了這個問題的答案,然后挑選出一些答案,翻譯出來。下面就是一些回答的原文和翻譯(稍有修改),包括回答者的名字我也列出來了~
1. Bart van Ingen Schenau的回答
There is a very solid reason for this: const in C does not mean something is constant. It just means a variable is read-only.
In places where the compiler requires a true constant (such as for array sizes for non-VLA arrays), using a const variable, such as fieldWidth is just not possible.
這有個很可靠的原因:const在C中不表示一個變量是常量。const只表示一個變量是只讀的。
在編譯器需要一個真正的常量的情況下(例如不可變長數組的大小),使用const變量,例如fieldWidth是不可能的。
2. Vovanium回答
They're different.
const is just a qualifier, which says that a variable cannot be changed at runtime. But all other features of the variable persist: it has allocated storage, and this storage may be addressed. So code does not just treat it as a literal, but refers to the variable by accessing the specified memory location (except if it is static const, then it can be optimized away), and loading its value at runtime. And as a const variable has allocated storage, if you add it to a header and include it in several C sources, you'll get a "multiple symbol definition" linkage error unless you mark it as extern. And in this case the compiler can't optimize code against its actual value (unless global optimization is on).
#define simply substitutes a name with its value. Furthermore, a #define'd constant may be used in the preprocessor: you can use it with #ifdef to do conditional compilation based on its value, or use the stringizing operator # to get a string with its value. And as the compiler knows its value at compile time it may optimize code based on that value.
For example:
#define SCALE 1 ... scaled_x = x * SCALE;
When SCALE is defined as 1 the compiler can eliminate the multiplication as it knows that x * 1 == x, but if SCALE is an (extern) const, it will need to generate code to fetch the value and perform the multiplication because the value will not be known until the linking stage. (extern is needed to use the constant from several source files.)
A closer equivalent to using #define is using enumerations:
enum dummy_enum { constant_value = 10010 };
But this is restricted to integer values and doesn't have advantages of #define, so it is not widely used.
const is useful when you need to import a constant value from some library where it was compiled in. Or if it is used with pointers. Or if it is an array of constant values accessed through a variable index value. Otherwise, const has no advantages over #define.
它們不一樣。
const只是個限定符,表示一個變量不能在運行時間被修改。但其他所有屬於變量的特性仍保留着:它有已分配的存儲器(原文是allocated storage),而且這個存儲器可能有地址。所以代碼不將它(const變量)看作常量,而通過訪問指定的內存位置指代該變量(除非是static const,這樣它就會被優化),然后再運行時間加載它的值。然后因為const變量有已分配的存儲器,如果你將它加入一個頭文件然后在多個C源代碼文件中包含它,你會得到一個“符號重定義”的鏈接錯誤,除非你將它標記為extern。而且在這種情況下,編譯器不能針對其真實值優化代碼(除非打開全局優化)。
#define簡單地用一個值替代一個名字。此外,一個#define定義的常量可以在預處理器中使用:你可以將其和#ifdef一起使用,在它的值的基礎上做條件編譯,或者使用連接符#以獲取一個值對應的字符串。並且因為編譯器在編譯時知道它的值,編譯器將可以在該值的基礎上進行優化。
舉個例子:
#define SCALE 1 ... scaled_x = x * SCALE;
當SCALE被定義為1時,編譯器可以直接去掉這個乘法運算,因為它知道x * 1 == x。但如果SCALE是一個(extern)const變量,編譯器就會需要生成代碼以獲取其值,然后進行乘法運算,因為SCALE的值在鏈接階段以前都是未知的(在多個源代碼文件中使用該const變量時需要extern)。
另一個更接近於#define的方法是枚舉量:
enum dummy_enum { constant_value = 10010 };
但枚舉量被限制為整數,與#define相比沒有優勢,因此使用不廣泛。
在需要從庫中導入常量值時const很有用;或者其和指針一起使用;或者其為一個通過索引值訪問的常量數組。否則,const對於#define沒有優勢。
3. R..的回答
The reason is that most of the time, you want a constant, not a const-qualified variable. The two are not remotely the same in the C language. For example, variables are not valid as part of initializers for static-storage-duration objects, as non-vla array dimensions (for example the size of an array in a structure, or any array pre-C99).
原因是因為在大多數情況下,你想要一個常量,而不是有const限定符的變量。兩者在C中不完全一樣(原文是note remotely the same,不知道有沒有犯錯)。例如,變量作為靜態存儲周期對象的initializer的一部分是非法的,例如不可變長數組的大小(例如結構中一個數組的大小,或者C99前的任何數組)。
翻譯了一部分,也不知道有沒有錯誤,如果有錯誤請指出~
看了3個回答,我想答案已經十分明顯了。
C中的const和C++的不同。在C中,const定義的常量和#define定義的常量不完全相同。#define是預處理器指令,在編譯前就會把所有#define定義的常量的名字全部替換為其值。const定義的常量等同於只讀變量,值在鏈接時才會知道。(我想,我之所以會有這個問題,是因為我直接學了C++而不是先學C,而C和C++中的const不一樣。)
因此const定義的常量對於編譯器就不是100%的常量,數組長度不能是const常量,只能是#define定義的常量。條件編譯的時候也只能使用#define定義的常量。
那么也不是每個常量都是表示數組大小的吧,剩下的常量為什么也是用#define定義的呢?以我naive的思維,估計是因為為了代碼風格上的統一吧。
那么在C++中為什么還有很多#define呢?那估計就是繼承了C的習慣吧,或者為了兼容C吧……不過,如果是C++,建議使用const,而不是#define,來定義常量。
本文可轉載,轉載請注明出處:http://www.cnblogs.com/collectionne/p/6713651.html。