const關鍵字與數組、指針

開始回顧C基礎知識。C中使用指針是很危險的事情,一個不慎就會造成程序崩潰,因此對於傳入函數的參數進行保護就是必須的了,特別是針對數組。

const關鍵字

const關鍵字用於將一個變量聲明爲只讀,也就是常量,無法被修改。

const int constant = 10;//聲明constant爲常量的同時對它進行初始化賦值
int const constant = 10;//也可以將const放在int後面

const修飾數組

使用const來修飾數組聲明瞭一個數組常量,是對數組裏面數據的一種保護,當試圖修改一個被const修飾的數組內容時,編譯時會產生錯誤。

const int days[5] = {1,2,3,4,5};//int const days[5]一樣
//想要把days[0]重新賦值爲6,報錯
days[0] = 6;
//Cannot assign to variable 'days' with const-qualified type 'const int [5]'

但是我們有一點要注意,是不是days裏面的數據一定無法修改呢?我們做個試驗:

 	const int days[5] = {1,2,3,4,5};
	int * p = days;
    *p = 6;
    for (int i = 0; i < 5; ++i) {
        printf("%d\n",*p++);
    }

結果:

6
2
3
4
5

所以雖然數組days被聲明爲只讀的,但是如果通過指針去訪問數組,還是可以改變數組元素的,這也就是指針的強大與易錯。

const修飾指針

const修飾指針創建了一個指針常量,但是const的位置會導致這個指針常量有不同的含義。

	int days[5] = {1,2,3,4,5};
    const int *p1;//const修飾的是int,表示p1指向的變量值不可改變,指針本身可以改變
    //p1指向的值爲常量
    p1 = days;
    *p1 = 6;//報錯,不允許修改指針指向的值。Read-only variable is not assignable
    p1[1] = 7;//報錯,不允許修改
    days[0] = 6;//允許,days不是常量
    p1++;//合法,p1這個指針本身是可以修改的,這裏讓其指向days的第二個元素
    
    
    int * const p2 = days;//const修飾的是p2,表示p2這個指針本身是無法修改的,但是其指向的值是可以修改的
    //這裏p2本身是常量,因此聲明p2的時候就要初始化,否則後面無法對p2進行初始化
    *p2 = 10;//合法,p2指向的值可以修改
    p2 = &days[1];//不合法,報錯,p2是常量,因此想要修改指針的值使其指向days[1]不合法。
    //Cannot assign to variable 'p2' with const-qualified type 'int *const'

上面就說明了兩種const修飾的指針常量的區別。這裏有以下幾點需要注意:

  • 將常量或非常量數據的地址賦值給指向常量的的指針是合法的。但是非常量數據的地址可以賦值給普通指針,而常量數據的地址就不可以賦值給普通指針。這樣做只會提示不合法,卻仍然可以這樣操作,但最好不要這樣做,數據既然數據已經被聲明爲常量,那麼就不要試圖去修改,因此指針不要這樣賦值,以免修改了倡廉打個值,就像上面const修飾數組裏面說的。
	double un_locked[3] = {1.2,2.3,3.1};
    const double locked[3] = {1.0,2.0,3.0};
    const double * p3 = locked;//合法
    p3 = un_locked;//合法
    p3 = &un_locked[1];//合法
    double *p4;
    p4 = un_locked;//合法
    p4 = locked;//非法,但是程序可以運行,
  • const用來修飾形式參量。C語言的傳參特性這裏不提,如果函數並不想修改本來的數據,一般會把相應的形式參量修飾爲const的,告訴編譯器這裏要把傳進來的指針地址當做常量來對待,不允許修改,當函數體內部想要做修改時,編譯器會報錯。需要注意的是並不要求傳進來的參數是常量,而是編譯器這樣做保證函數執行過程中對源數據不會修改而已。
void foo(const int *bar);
//foo接受一個指針,並把這個指針當做常量對待
void foo1(int *bar);
//foo1聲明接受一個普通指針
int main() {
    int test1[2] = {1,2};
    const int test2[2] = {3,4};
    
    foo(test1);//合法
    foo(test2);//合法
    foo1(test1);//合法
    foo1(test2);//不合法,不提倡這樣做。Passing 'const int [2]' to parameter of type 'int *' discards qualifiers
}

void foo(const int *bar){
}
void foo1(int *bar){
}

用兩個const修飾指針

用兩個const修飾符修飾指針會使得這個指針本身既不可以更改所指向的地址,也無法修改所指向的數據。

 	int days[3] = {1,2,3};
    const int * const p = days;
    
    p = &days[2];//不合法
    *p = 6;//不合法

const修飾函數本身我還沒用過,碰到了再來補上。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章