天天看點

【C語言進階剖析】9、const 和 volatile 分析

const 關鍵字有如下特點:

const 修飾的變量本質上還是一個變量,隻不過這個變量是隻讀的

const 修飾的局部變量在棧上配置設定空間

const 修飾的全局變量在全局資料區配置設定空間

const 隻在編譯器有用,在運作期無用

注意:const 修飾的變量不是真正的常量,隻是告訴編譯器該變量不能出現在指派符号的左邊。const 變量隻是說我不會修改這塊記憶體,并不代表别人不修改。

對于 const 修飾的局部變量在棧上配置設定記憶體,其值還是可以更改的。

對于 const 修飾的全局變量

标準 c 語言編譯器不會将 const 修飾的全局變量存儲在隻讀存儲區,而是存儲于可修改的全局資料區,其值依然可以改變;

現代 c 語言編譯器中,修改 const 全局變量将導緻程式崩潰,因為現代 c 編譯器中的 const 将具有全局聲明周期的變量存儲于隻讀存儲區。

程式實驗:const 的變量本質

【C語言進階剖析】9、const 和 volatile 分析
對上面的結果:const 修飾的局部變量值可以修改, const 修飾的全局變量存儲于隻讀存儲區,修改會導緻程式崩潰

c 語言中的 const 使得變量具有隻讀屬性

現代 c 編譯器中的 const 将具有全局生命周期的變量存儲于隻讀存儲區

const 不能定義真正意義上的常量,隻是表示我不去修改這個變量。
對上面的程式,全局變量和靜态局部變量都具有全局生命周期,使用 const 修飾,變量存儲于隻讀存儲區,不可修改。i 和 array[5] 是局部變量,雖然具有隻讀屬性,僅僅表示通過變量 i 和 array 不會修改記憶體,并不代表别人不去修改。

const 修飾的函數參數表示在函數體内不希望改變參數的值

const 修飾的函數傳回值表示傳回值不可改變,多用于傳回指針的情況。

小貼士:c 語言中的字元串字面量存儲于隻讀存儲區中,在程式中需要使用 const char* 指針。 const char* s = “hello world”;

執行個體分析:const 修飾的函數參數與傳回值

編譯結果如下:編譯器提示,變量 i 是隻讀變量,不能修改。函數 f() 傳回的是一個 const 類型的指針,将其指派給一個普通指針,有修改的可能,給出警告。

【C語言進階剖析】9、const 和 volatile 分析

是以,這裡不能修改變量 i 的值;應該将指針 p 改為 const char* p;并且不能修改指針 p 指向的内容。

volatile 平時使用較少,這裡就來說一下這個關鍵字的作用。

volatile 可以了解為”編譯器警告訓示字“,什麼意思呢,就是告訴編譯器必須每次去記憶體中取變量值,防止編譯器對代碼進行優化。我們看一個例子:

【C語言進階剖析】9、const 和 volatile 分析

對上面的代碼,編譯器在編譯的時候發現 obj 沒有被當作左值使用,是以會”聰明“的直接将 obj 替換成 10,而把 a 和 b 都指派為10。

這樣做會不會有問題呢,看似沒有修改 obj,但是在多線程的程式中,或者在需要進行中斷請求的程式中,不能保證其他線程或者中斷請求對這塊記憶體進行修改,在對 b 指派的時候,可能 obj 的值已經改變了,是以 b 得到的值是不正确的。

是以,volatile 主要修飾可能被多個線程通路的變量,也可以修飾可能被為止因素更改的變量,比如中斷處理。

小問題:const volatile int i = 0; 變量 i 具有什麼樣的特性,編譯器如何處理這個變量? 解析:首先,變量 i 是 int 型的變量,每次對 i 操作都是對直接去記憶體中取,并且這個變量是隻讀的。

1、const 使得變量具有隻讀屬性

2、const 不能定義真正意義上的常量

3、const 将具有全局生命周期的變量存儲在隻讀存儲區

4、volatile 強制編譯器減少優化,必須每次從記憶體中取值

【C語言進階剖析】9、const 和 volatile 分析