注:緩存
因爲從沒有使用過 volatile 這個關鍵詞,因此如下內容中,關於 volatile 的說明可能不是正確的.
spa
在編譯期看來,const,volatile 是變量的屬性,以下:線程
const volatile int i = 33; // 編譯期會將 i 看成一個變量,其中"int"代表了該變量的類型,"33"則指定了變量的初始值; // 而 "const","volatile" 則認爲是變量 i 的屬性,其中 // const 代表變量 i 的值不能夠被修改 // volatile 告訴編譯期每一次讀取 i 的值時都從內存中讀取,而不是從緩存中(如寄存器).
用來修飾一個變量,告訴編譯期翻譯
int i = 10; int a = i; sleep(3); int b = i; // 則編譯期翻譯的彙編代碼多是: mov eax,i ; mov a,eax ; 將 i 賦值給 a. call sleep ; 在此以前可能須要插入參數. mov b,eax ; 將 i 賦值給 b.此時直接從寄存器中讀取數據,減小了內存訪問次數. // 當使用了 volatile 關鍵詞後,即:volatile int i = 33;編譯期翻譯的代碼可能以下: mov eax,i ; mov a,eax ; call sleep ; mov eax,i ; 始終從內存中訪問 i 的值. mov b,eax ; // 第 2 個程序,演示修改變量的值後,將新值寫入到內存的必要性. int i = 0; void thread_func(){ lock(); // 獲取 i 的保護鎖. i = i+1; unlock(); } // 則此時編譯器編譯結果多是: call lock(); mov eax,i; inc eax // mov i,eax;//編譯器爲了提升效率而可能不會當即將新值寫入到內存中,因此可能沒有該指令. call unlock(); // 這樣若 2 個線程都同時執行 thread_func(),在線程 1 獲取鎖,並修改 i 的值,而後釋放鎖;此時線程2看到的 i 將仍然是 0.
int const *iptr = &i;int *const iptrc = &i;這兩個語句的區別,首先要知道 iptr,iptrc 也是一個變量,其類型爲 int* 類型,代表該變量的值是一個地址,指向着一個 int 類型的變量.指針
int const *iptr; const 的做用範圍是 *iptr,即此處 const 並非代表 iptr 的值不能夠修改,而是 iptr 指向的 int 類型變量(即 i 的值)不能夠修改.code
int * const iptrc; const 的做用範圍是 iptrc,代表變量 iptrc 的值不能夠修改,可是 iptrc 指向的 int 類型變量是能夠修改的,以下:ip
int i = 33; int const *iptr = &i; int * const iptrc = &i; ++(*iptr); // 錯誤,increment of read-only location ‘* iptr’ ++iptr; // 正確; ++(*iptrc);// 正確 ++iptrc; // 錯誤,increment of read-only variable ‘iptrc’
volatile,const 的修飾範圍爲從 const,volatile 所在的位置到變量名處.以下:內存
int const ci = 33; // const 做用範圍是 ci;代表變量 ci 的值是不能夠修改的. int const *ciptr = &ci; // const 的做用範圍是"*ciptr",代表 ciptr 指向的 int 類型變量的值是不能夠修改的. int const * const ciptrc = &ci; // 第 1 個 const 的修飾範圍是 *ciptrc,代表 ciptrc 指向的 int 類型變量的值是不能夠修改的. // 第 2 個 const 的修飾範圍是 ciptrc,代表變量 ciptrc 的值是不能夠修改的. int const ** ciptrptr = &ciptr; // const 的修飾範圍是 **ciptrptr, int const * const *ciptrcptr = &ciptrc;