指標常數本質是一個常數,而用指標修飾它,那麼說明這個常數的值應該是一個指標。指標常數 的值是指標,這個值因為是常數,所以不能被賦值。
因為指標常數是一個常數,在宣告的時候一定要給它賦初值。一旦賦值,以後這個常數再也不能指向別的地址。下面的例子展示了指標常數不同於指向常數的指標:
int var; // 一個int型別的物件
int *const c_ptr = &var; // 一個int型別指標常數
*c_ptr = 123; // 合法:我們可以修改它所參照的物件
++c_ptr; // 錯誤:我們不能修改指標
當一個指標指向具有 const 限定的物件,稱為指向常數的指標,可以修改該指標的值。然而,只能使用這樣的指標來讀取所指向的物件,但不能修改所指向的物件。因此,指向常數的指標常常被稱為唯讀指標(read-only pointer)。
所參照物件本身可以是常數,也可以不是常數。例子如下:
int var; //一個int型別的物件
const int c_var = 100, // 一個int型別的常數物件
*ptr_to_const; // 一個指向常數的指標:指標本身不是常數!
ptr_to_const = &c_var; // 合法:使得ptr_to_const指向c_var
var = 2 * *ptr_to_const; // 合法:等效於var = 2 * c_var
ptr_to_const = &var; // 合法:使得ptr_to_const指向var
if ( c_var < *ptr_to_const ) // 合法:“唯讀”方式獲取
*ptr_to_const = 77; // 錯誤:我們不能使用ptr_to_const修改var,
// 儘管var不是常數
型別修飾符和型別限定符可以以任何順序排列。因此,下面的寫法是合法的:
int const c_var = 100, *ptr_to_const;
賦值表示式 ptr_to_const=&var 必需採用隱式轉換:int 指標值 &var 會自動地轉換成左運算元的型別,也就是指向 const int 的指標。對於與之類似的型別運算元的運算子,編譯器會隱式地將指向某一型別T的指標,轉換為具有更多限定符的型別 T 的指標。
如果想將一個指標轉換為有較少限定符的型別,必須使用顯式的型別轉換。下面的程式程式碼片段使用前面例子所宣告的變數:
int *ptr = &var; // 一個指向var的int指標
*ptr = 77; // 合法:ptr 不是一個唯讀指標
ptr_to_const = ptr; // 合法:隱式地將ptr從指向int的指標
// 轉換為指向int常數的指標
*ptr_to_const = 77; // 錯誤:不能通過一個唯讀指標修改一個變數
ptr = &c_var; // 錯誤:不能隱式地將指向int常數的指標轉換
// 為指向int 的指標
ptr = (int *)&c_var; // 合法:顯式的指標型別轉換總是可行的
*ptr = 200; // 嘗試修改c_var:可能會造成執行錯誤
如果編譯器將常數物件 c_var 放置在記憶體中的唯讀區域,那麼最後一條語句將會引發執行錯誤。
也可以宣告指向常數的常數指標,如下面函數原型的引數宣告:
void func( const int * const c_ptr_to_const );
該函數的引數是唯讀指標,當該函數被呼叫時該唯讀指標引數會被初始化,並且在函數執行過程中保持該值不變。