iT邦幫忙

1

【c/c++學習筆記】難懂的const關鍵字,const v.s. 指標

今天要介紹的是c/c++語言的關鍵字-const
簡單來說,const是constant,常數的縮寫,
常數就是恆常不變的數值,
一但經初始化就無法再改變其值,
而且必須在宣告的時候便初始化

基礎語法教學

譬如說直接宣告const int但未給初始值會出錯:

const int number; //錯誤: const必須初始化

必須宣告時即給定初始值,並且事後無法修改,
譬如:

const double PI = 3.14;
PI = 4.0; //錯誤: 常數無法修改

到這邊為止應該還算好懂,
然而若宣告一個const指標,
情況則複雜的多

const 指標

(不了解指標的讀者可先移步至c/c++語言: 超好懂的指標(pointer)與參考(reference),歡迎初學者)
若以const宣告指標,
有以下三種情況:

char c = 'A';
const char * p1 = &c;
char * const p2 = &c;
const char *  const p3 = &c;

const 指標一樣必須初始化,
但可以放在char *前面或後面(或前後都放),
這三種宣告方式有什麼區別呢?

回顧一下指標是代表一個地址,
一般狀況下,你可以改變地址本身,或者透過地址去改變裡面的內容,
如範例:

char c = 'A';
char other = 'B';
char * p = &c;
p = &other; //改變p指向other的地址
*p = 'D'; //透過地址修改other變數的內容

所以const可以放在兩個地方,
可以理解為兩種不同的限制,
一是限制「不可以改變地址本身」,
二是限制「不可以透過地址去改變變數的內容

一般教科書都會建議要讀懂變數宣告要從右到左閱讀(雖然我覺得好像這樣也沒比較好閱讀),
反正你若自己有一套方法記住每個宣告是做什麼用的就行

char * const p2 = &c; 限制不可以改變地址本身

變數宣告從右看到左,
看到const用來修飾 p2,
表示p2這個物件本身是一個const,
p2又是一個指標,
所以代表指標本身所指的地址不能改變

char c = 'A';
char * const p2 = &c;
*p2 = 'B'; //合法,可透過地址改變值
char other = 'C';
p2 = &other; //不合法,不可以改變指標本身

const char * p1 = &c; 限制不可以透過地址去改變變數的內容

const用來修飾型別char,
表示這個指標指向的char變數是不能改變的,
也就不能透過地址去改變變數的內容,
如範例:

char c = 'A';
const char * p1 = &c;
*p1 = 'B'; //不合法,不可透過地址改變值
char other = 'C';
p1 = &other; //合法,可以改變指標本身

const char * const p3 = &c; 既不能改變地址本身,也不能透過地址去改變變數的內容

加上兩個const的宣告則比較單純,
想當然爾就是什麼都不能改變,
不論想修改指標本身或是改內容都不行

char c = 'A';
const char *  const p3 = &c;
*p3 = 'B'; //不合法,不可透過地址改變值
char other = 'C';
p3 = &other; //不合法,不可以改變指標本身

延伸思考: 變數是const,但指向它的指標不是會怎樣?

考慮一段程式碼:

int main()
{
    const char c = 'A';
    char * const p = &c;
    *p = 'D';
    return 0;
}

我們設定字元c是一個const char
根據const的效果,字元c一旦設定就不能修改

再設定p是一個不能改變地址的指標指向c(但根據上述效果說明,p所指的內容改變則不受限制),
那麼請問可否透過*p = 'D';改變變數c的值呢?
讓你想一想,猜一下結果如何?





叮~ 答案是程式無法編譯通過
const char的效果使得字元c無法被修改,
char * const p = &c的效果又可以修改指標所指的內容,
這不自相矛盾嗎?

就如你玩一款遊戲,拿著絕世武器去砍一隻魔王,

  • 武器效果: 攻擊傷害無法被減免
  • 魔王技能效果: 本回合不會受到任何傷害

那麼到底是矛會贏還是盾會贏呢?
恐怕只有更明確的效果定義或是實測才知道了


尚未有邦友留言

立即登入留言