C與C++中 const 的區別

常量與const?

什麼是常量?
常量就是一個不變的量,或者說就是一個字面值,但是const指定的量不一定是一個常量。
在C語言中,const更確切來說指定的是一個只讀變量。
而C++中,const只是指定向編譯器尋求宏替換
(可能這句話你會有點陌生,沒關係,後面會詳細講解)

那麼C/C++中的const指定的量真的就一成不變嗎?或者說真的就安全嗎?
我們在.c文件下(c語言環境)運行以下程序:
在這裏插入圖片描述
(注意:需要對&a做一次強制類型轉換,不然會報warning,甚至error)

輸出結果:
我們發現雖然a被我們定義成了const int 變量,但只要得到了它的地址,仍然是能夠修改它的值的。

同樣的代碼,我們在.cpp文件(C++環境)下再運行一次

在這裏插入圖片描述
輸出結果:
在這裏插入圖片描述
我們可以發現,p確實得到了a的地址,但是改變*p,a卻沒有變化了,這是爲什麼?

原因:
還記得我之前那句話嗎?
在C語言中,const更確切來說指定的是一個只讀變量。而C++中,const只是指定向編譯器尋求宏替換。
C語言中,const指定一個只讀變量,其終究是一個變量,可以修改的,如何修改?就是上面測試時用的方法–訪問其內存。但我們也不能忽略其只讀性,也就是說,單純訪問該變量應該注意它的只讀性,甚至語法要求你只能在初始化時對他進行一次值修改。

而在C++中,const只是指定向編譯器尋求宏替換。宏替換是編譯期進行的,替換的東西是:把所有出現const變量的地方換成一個字面值。這就可以解釋在C++下運行爲什麼會出現不同的結果:當我們第二條輸出語句輸出a時,其實輸出的是預編譯期就確定下來的一個字面量,而*p是程序運行期才確定下來的。所以,a在內存中的值確實已經被修改了,只是我們看不到而已。

讓我們看一段反彙編代碼,來證實以上說法:
在這裏插入圖片描述
可以看到在 int b = a; 這一句下面,其執行的是直接將0Ch,也就是12直接賦值給了b,而沒有去訪問a內存的值。

但是:C++這樣做就安全了嗎?
既然C++中的const只是在編譯期進行了宏替換,那如果const變量的值是在預編譯期不能知道的呢?
如果你不能理解什麼意思,請看以下程序。
在這裏插入圖片描述
輸出結果:
在這裏插入圖片描述
可以發現a的值這次能看出來真的被改變了,其原因是:對a的初始化不再是一個預編譯期能確定的值了,所以編譯器沒辦法幫你完成宏替換了。

反彙編驗證一下:
在這裏插入圖片描述
在 int b = a這一句下面,可以看到,這次並沒有直接用字面值賦值,也就是說沒有宏替換,而是dword ptr[a],訪問內存中a的值給b。

更騷一點,我們可以對一個頂層指針也探究一下,畢竟指針也是一個變量。
測試代碼

在這裏插入圖片描述
同樣,用字面量初始化的指針,被進行了宏替換,其值看起來沒有改變,但是以一個變量初始化的頂層指針,已經被改變。雖然本質上兩者內存的值都已經改變。

總結:

const並不能保證一個變量始終不變,如果你不想它的值被改變,就不要訪問內存去改變它。另外,C++中的指針是很靈活的,它可以被強制類型轉換成任何你需要的類型,所以當你能夠得到一個變量的地址時,這個變量就變得不那麼安全了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章