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

建議11:盡量使用const聲明值不會改變的變量

從字面上理解,const是constant的縮寫,是恒定不變的意思,也翻譯為常量、常數等。正是因為這一點,看到const關鍵字,很多人就認為被const修飾的值是常量。其實,在C語言中,關鍵字const的功能非常強大,它不僅可以用來修飾普通變量、數組變量與指針變量等,還可以用來修飾函數的參數、返回值與函數本身。這些將會在后面的章節逐一詳細講解,本節只討論使用const來修飾變量的情況。

對變量來說,const關鍵字可以限定一個變量的值不允許被改變,從而保護被修飾的東西,防止意外修改發生,這在一定程度上可以提高程序的安全性和可靠性。但是要正確地使用const變量,我們必須弄清以下幾點。

1.const變量是只讀變量,不是常量

提到const變量,總有人喜歡把它和常量混為一談。其實const變量不是常量,準確地說它應該是只讀的變量。為了讓大家更好地區分這兩個概念,我們來看下面的例子:


const int array_num=10;
int arr[array_num]={1,2,3,4,5,6,7,8,9};

在標準的ANSI C中,上面的這種寫法是錯誤的,因為數組的大小應該是個常量,而const int array_num只是一個只讀變量。雖然常量也是只讀的、不可修改的(例如10、‘C’等),但只讀變量卻不等于常量,只讀變量被編譯器限定為不能夠被修改。

實際上,根據編譯過程及內存分配來看,這種用法本來應該是合理的,只是ANSI C對數組的規定限制了它。而在C++中,上面的這種寫法確實是正確的。

2.確保變量的值不被修改

可以說,const關鍵字的最大作用就是確保變量賦初值之后,其值不會被任何程序修改。如下面的示例代碼所示:


const int array_num=10;
array_num++;            // 錯誤,不可以被修改

很顯然,語句“array_num++”是錯誤的。同樣,對于外部變量,const一樣可以確保其變量的值不被修改,如下面的代碼所示:


extern const int i;       // 正確的引用
extern const int i="10";      // 錯誤,不可以被再次賦值

盡管如此,網上仍然流傳著一種修改const變量的說法,如代碼清單1-30所示。

代碼清單1-30 const變量使用示例


#include <stdio.h>
int main(void)
{
    const int i1=10;
    int *p1=(int *)&i1;
    int *p2=p1;
    *p1=100;
    printf("%d %d %d\n",i1,*p1,*p2);
    printf("%p %p %p\n\n",&i1,p1,p2);
    return 0;
}

有人說,這樣const變量就能被修改了,但運行上面的程序,const變量的值根本沒有改變,代碼清單1-30的運行結果如圖1-45所示。

圖1-45 代碼清單1-30的運行結果

在圖1-45中,雖然“i1,*p1,*p2”所得的值不同,但“&i1,p1,p2”卻是同一個地址,既然是同一地址,為什么輸出不一樣的值?

為了進一步查看其原因,我們在代碼清單1-30中添加如下一條語句:


printf("%d\n",*((int *)0x0012FF74));

這樣就可以直接輸出地址所存的值了。得到的結果在我們的預料之中,為“100”。或許大家認為這樣就改變了const變量的值。

其實,“int*p1=(int*)&i1;”表面上給了它們相同的指針,但是const變量的值是保存在數據段(只讀)的,通過地址0x0012FF74查內存文件可得知其屬于堆棧段。也就是說,雖然地址相同,但const變量讀取的是數據段,而通過指針讀取到的是堆棧段。

由此可見,const提供了一種保護機制,能在編譯階段阻止其變量的值被修改。但它并不能完全防止在程序的內部(甚至是外部)來修改這個值。也就是說,const變量是只讀變量,既然是變量,那么就可以獲取其地址,然后修改其值。因此,當匯編成二進制之后,這種保護機制就不復存在了。

3.節省空間,避免不必要的內存分配

使用const變量除了可以確保變量值不被修改之外,同時它還可以節省存儲空間,避免不必要的內存分配。通常,編譯器并不為普通const只讀變量分配存儲空間,而是將它們保存在符號表中,這使得它成為一個編譯期間的值,沒有了存儲與讀內存的操作,從而提高效率。

主站蜘蛛池模板: 德庆县| 靖宇县| 谷城县| 唐山市| 石台县| 怀远县| 建德市| 孝昌县| 封开县| 贞丰县| 乐山市| 勐海县| 长寿区| 井冈山市| 长兴县| 新沂市| 洪洞县| 灵石县| 太仆寺旗| 化隆| 瓮安县| 洪雅县| 正定县| 台东县| 绿春县| 内黄县| 财经| 孟州市| 丰原市| 龙海市| 金平| 正安县| 玉田县| 逊克县| 广东省| 依安县| 湘阴县| 孝义市| 罗源县| 新龙县| 北流市|