c和c 關於const的一些區別

2022-05-08 21:06:16 字數 1735 閱讀 2756

以下參考了網上的一些資料並通過程式驗證。

注意,以下情況都是用gcc和g++編譯器得到的結果,用vs編譯器又會有所不同。

以下說下c和c++中const定義的常量的一些區別:

c++中用const定義了乙個常量後,不會分配乙個空間給它,而是將其寫入符號表(symbol table),這使得它成為乙個編譯期間的常量,沒有了儲存與讀記憶體的操作,使得它的效率也很高。但是const定義的常量本質上也是乙個變數,是變數就會有位址,那麼什麼時候會分配記憶體?看看下面的**:

int

main()

結果:

我們看到,通過 int*p = (int*)(&a);這種方法,可以直接修改const常量對應的記憶體空間中的值,但是這種修改不會影響到常量本身的值,因為用到a的時候,編譯器根本不會去進行記憶體空間的讀取。這就是c++的常量摺疊(constant folding),即將const常量放在符號表中,而並不給其分配記憶體。編譯器直接進行替換優化。除非需要用到a的儲存空間的時候,編譯器迫不得已才會分配乙個空間給a,但之後a的值仍舊從符號表中讀取,不管a的儲存空間中的值如何變化,都不會對常量a產生影響。

但是在c中卻不是這樣.c沒有constant folding的概念,用constant定義乙個常量的時候,編譯器會直接開闢乙個記憶體空間存放該常量。不會進行優化。同樣的例子在c下面會產生不同的結果:

1

intmain()

2

結果:

我們看到,在c裡面,乙個被const定義為常量的值,堂而皇之地被修改了,而且編譯器沒有報任何錯誤 !

如果我們進一步深入可以發現,對於以上兩個例子來說,a都是定義在某個函式之內的(比如main()函式),不管是c還是c++,本質上都只是將其當成乙個普通的區域性變數來對待,都只是在棧上分配空間。所以const根本就不能起到阻止修改其記憶體空間的作用,乙個合法的強制型別轉換就可以輕鬆搞定。c++比c好的地方就在於使用了constant folding的機制,使得常量的值跟對應的記憶體空間無關,從而保護了該常量值。

以上的例子是針對區域性的const常量而言,對全域性的const變數,c++仍舊採用constant folding策略,故以下**是行得通的:

//

global variable

const

int a = 3

;int arr[a];

但是c會報錯: error: variably modified 'arr' at file scope, 原因在於gcc認為a只是乙個普通的全域性變數,而變數是不能用來指定陣列的長度的。當然,這是針對全域性陣列而言,如果是區域性的陣列的話,就算是int a = 3; int arr[a];這種都是可以的,因為c裡面還有一種叫變長陣列的東西(我暈~,貌似因為兩者的實現機制不一樣,這個要再看看)

另外,對於a,在c和c++中如果我們仍然用int *p = (int*)(&a);這種方法來修改它記憶體中的值,編譯時不會報錯,但是執行時會報段錯誤,因為a是放在唯讀的全域性資料區中,修改該區中的資料會引發段錯誤。

在vs編譯器下:

1.不支援變長陣列,乙個變數除非被宣告為const,否則不能用來宣告陣列的長度。

2.const變數,不管是全域性的還是區域性,都是放在唯讀資料區,所以無法用前面的方法來修改記憶體空間裡面的值,編譯時就會報錯。

關於C 中const的一些研究

最近複習的過程中發現網上對於const的說法不一,讓人摸不著頭腦,為了搞清其原理,決定通過反彙編的方式來看一看其內部究竟發生了什麼,下面是一篇簡單的介紹反彙編指令的文章,用來理解本次所研究的東西已經足夠 下面將按照乙個觀點乙個例子的方式來進行 該測試基於vs2017環境 1.將字面值賦給const變...

c 中關於const的一些細節問題

const是一件奇妙的事情,它指定乙個語義約束,而編譯器會強制執行這項約束,它允許你告訴編譯器或者其他程式設計師某值應該保持不變。你可以用const修飾class內部的static和non static成員變數,你也可以指出指標之身或者是指標所指物,或者兩個都是。比如 char greeting h...

C和C 的一些語法區別

struct 在c語言中,試用定義的struct型別的變數方式 struct 定義的變數 生成的變數 在c 語言中,試用定義的struct型別的變數方式 struct 定義的變數 生成的變數 或者 定義的變數 生成的變數 在c語言中struct定義的變數中不能有函式,而在c 中可以有函式。函式的引數...