官术网_书友最值得收藏!

5.5 實際應(yīng)用中如何定義常量

如果要為程序中多個編譯單元或者多個模塊定義統(tǒng)一的符號常量,在C程序中你常常會把它定義在哪里呢?在C++程序中你又常常會把它定義在哪里呢?如果是只為某一個編譯單元定義符號常量,又當(dāng)如何?

表5-1是我們常用的做法。

表5-1 常用做法

(續(xù)表)

顯然,在C程序和C++程序中定義符號常量是有區(qū)別的。我們僅討論“多個編譯單元公用符號常量”的聲明和定義。

在C程序中,const符號常量定義的默認(rèn)連接類型(Linkage)是extern的,即外連接(external linkage),就像全局變量一樣。因此,如果要在頭文件中定義,必須使用static關(guān)鍵字,這樣每一個包含該頭文件的編譯單元就會分別擁有該常量的一份獨立定義實體(如同直接在每一個源文件中分別定義一次),否則會導(dǎo)致“redefinition”的編譯器診斷信息;如果在源文件中定義,除非明確改變它的連接類型為static(實際上是存儲類型為static,連接類型為內(nèi)連接)的,否則其他編譯單元就可以通過extern聲明來訪問它。

但是在C++程序中,const符號常量定義的默認(rèn)連接類型卻是static的,即內(nèi)連接(internal linkage),就像class的定義一樣,這就是在頭文件中定義而不需要static關(guān)鍵字的原因。

明白了C和C++符號常量的區(qū)別,就不難理解表5-1所列的幾種方法了。

這些做法各有優(yōu)缺點,如果是整型常量或者浮點常量,那么優(yōu)缺點都不是那么明顯。對于C++程序,我們比較一下方法二、四和方法一、三。

表5-2 方法比較

實際上,在大型應(yīng)用開發(fā)過程中,修改常量初值的事情并不會經(jīng)常發(fā)生,甚至極少會發(fā)生,即使是在維護(hù)階段,也不太可能變來變?nèi)ァR虼朔椒ǘ⑺妮^方法一、三的優(yōu)點就主要體現(xiàn)在存儲空間上了。如果是整型和浮點型常量,它們浪費的那點空間對一般應(yīng)用來說還不至于達(dá)到無法容忍的地步,不過對嵌入式應(yīng)用的開發(fā)來說也許是一件大事兒。

那什么常量最浪費空間呢?答案是字符串常量,尤其是較長的字符串常量。

字符串常量的定義和整型常量的定義差不多,但是其類型為const char *,因此我們常常這樣定義它們:

const char* const ERR_DESP_NO_MEMORY = "There is no enough memory!";

字符串常量可以在頭文件中定義并初始化,也可以在源文件中定義并初始化,但是二者差別較大:

? 如果在頭文件中定義并初始化,那么包含了該頭文件的每一個編譯單元不僅會為每一個常量指針常量(const char * const)創(chuàng)建一個獨立的拷貝項,而且也會為那個長長的字符串字面常量創(chuàng)建一個獨立的拷貝項,就相當(dāng)于在每一個編譯單元內(nèi)分別定義和初始化每一個常量一次。這是與整型或浮點型常量的定義不同的(它們在初始化完成后不再需要那個字面常量)。因此,每一個編譯單元內(nèi)訪問的字符串常量都是它自己單獨創(chuàng)建的拷貝。空間的開銷就體現(xiàn)在每一個字符串字面常量的獨立拷貝項上。

? 如果采用方法二,在頭文件中聲明所有常量指針常量,而在源文件中定義并初始化它們,則每一個包含該頭文件的編譯單元訪問的不僅是常量指針常量的唯一實體,而且字符串字面常量也是唯一的實體。這就大大節(jié)約了內(nèi)存,而且不影響效率。

當(dāng)然,我們完全可以把常量合并的優(yōu)化交給編譯器和連接器來完成,但是我們還是提倡由自己來優(yōu)化常量的定義。

主站蜘蛛池模板: 泽普县| 淳安县| 广丰县| 独山县| 平武县| 嘉定区| 互助| 连云港市| 凤山县| 清流县| 定远县| 洛隆县| 安宁市| 德江县| 惠安县| 五指山市| 砀山县| 涪陵区| 上高县| 西吉县| 牟定县| 江孜县| 大竹县| 双流县| 桂东县| 梁平县| 东明县| 遂宁市| 沙雅县| 桃江县| 昔阳县| 侯马市| 铜鼓县| 铁力市| 读书| 保定市| 徐闻县| 华蓥市| 本溪| 遂昌县| 平江县|