const修飾指標的三種效果,C語言const修飾指標詳解

2020-07-16 10:04:25
前面講過,當一個變數用 const 修飾後就不允許改變它的值了。那麼如果在定義指標變數的時候用 const 修飾會怎樣?同樣必須要在定義的時候進行初始化。比如:
int  a;
int  *p = &a;
當用 const 進行修飾時,根據 const 位置的不同有三種效果。原則是:修飾誰,誰的內容就不可變,其他的都可變。這三種情況在面試的時候幾乎是必考的,在實際程式設計中也是經常使用的,所以初學者一定要掌握。

1) const int*p=&a;

同樣 const 和 int 可以互換位置,二者是等價的。我們以放在最前面時進行描述。

當把 const 放最前面的時候,它修飾的就是 *p,那麼 *p 就不可變。*p 表示的是指標變數 p 所指向的記憶體單元裡面的內容,此時這個內容不可變。其他的都可變,如 p 中存放的是指向的記憶體單元的地址,這個地址可變,即 p 的指向可變。但指向誰,誰的內容就不可變。

這種用法常見於定義函數的形參。前面學習 printf 和 scanf,以及後面將要學習的很多函數,它們的原型中很多引數都是用 const 修飾的,這樣做的好處是安全!我們通過引數傳遞資料時,就把資料暴露了。而大多數情況下只是想使用傳過來的資料,並不想改變它的值,但往往由於程式設計人員個人水平的原因會不小心改變它的值。這時我們在形參中用 const 把傳過來的資料定義成唯讀的,這樣就更安全了。這也是 const 最有用之處。

所以如果你不想改變某個引數傳過來的值,那麼定義函數時就最好用 const 修飾這個引數,否則就不要用 const 修飾了。

2) int*const p=&a;

此時 const 修飾的是 p,所以 p 中存放的記憶體單元的地址不可變,而記憶體單元中的內容可變。即 p 的指向不可變,p 所指向的記憶體單元的內容可變。

3) const int*const p=&a;

此時 *p 和 p 都被修飾了,那麼 p 中存放的記憶體單元的地址和記憶體單元中的內容都不可變。

綜上所述,使用 const 可以保護用指標存取記憶體時由指標導致的被存取記憶體空間中資料的誤更改。因為指標是直接存取記憶體的,沒有拷貝,而有些時候使用指標存取記憶體時並不是要改變裡面的值,而只是要使用裡面的值,所以一旦不小心誤操作把裡面的資料改了就糟糕了。

但是這裡需要注意的是,上面第 1 種情況中,雖然在 *p 前加上 const 可以禁止指標變數 p 修改變數 a 中的值,但是它只能“禁止指標變數 p 修改”。也就是說,它只能保證在使用指標變數 p 時,p 不能修改 a 中的值。但是我並沒有說 const 可以保護 a 禁止一切的修改,其他指向 a 的沒有用 const 修飾的指標變數照樣可以修改 a 的值,而且變數 a 自己也可以修改自己的值。下面寫一個程式看一下:
# include <stdio.h>
int main(void)
{   
    int a = 10;
    const int *p = &a;
    int * q = &a;
    *q = 20;
    printf("a = %dn", a);
    a = 30;
    printf("a = %dn", a);
    //*p = 30;  //這麼寫就是錯的
    return 0;
}
輸出結果是:
a = 20
a = 30

可見,只有用 const 修飾過的指標變數 p 不能修改 a 中的內容,而沒有用 const 修飾過的指標變數 q 照樣可以修改 a 中的內容,而且 a 自己也可以重新給自己賦值。