轉《徹底搞定C指針》

一 .const int *pi與int const *pi

1.我先來說說const int *pi是什麼作用 (當然int const *pi也是一樣的,前面我們說過,它們實際是一樣的)。看下面的例子:

/* 代碼開始 */
int i1 = 30;
int i2 = 40;
const int *pi = &i1;
pi = &i2; /* 注意這裏,pi可以在任意時候重新賦值一個新內存地址*/
i2 = 80; /* 想想看:這裏能用*pi = 80來代替嗎?當然不能!*/
printf("%d\n", *pi); /* 輸出是80 */
/* 代碼結束 */
語義分析:
看出來了沒有啊,pi的值是可以被修改的。即它可以重新指向另一個地址的,但是,不能通過*pi來修改i2的值。這個規則符合我們前面所講的邏輯嗎?當然符合了!
首先const 修飾的是整個*pi(注意,我寫的是*pi而不是pi)。所以*pi是常量,是不能被賦值的(雖然pi所指的i2是變量,不是常量)。
其次,pi前並沒有用const 修飾,所以pi是指針變量,能被賦值重新指向另一內存地址的。你可能會疑問:那我又如何用const 來修飾pi呢?其實,你注意到int *const pi中const 的位置就大概可以明白了。請記住,通過格式看語義。哈哈,你可能已經看出了規律吧?那下面的一節也就沒必要看下去了。不過我還得繼續我的戰鬥!
2. 再看int *const pi
確實,int *const pi與前面的int const *pi會很容易給混淆的。注意:前面一句的const 是寫在pi前和*號後的,而不是寫在*pi前的。很顯然,它是修飾限定pi的。我先讓你看例子:
/* 代碼開始 */
int i1 = 30;
int i2 = 40;
int *const pi = &i1;
/* pi = &i2; 注意這裏,pi不能再這樣重新賦值了,即不能再指向另一個新地址。(第4行的註釋)*/
/* 所以我已經註釋了它。*/
i1 = 80; /* 想想看:這裏能用 *pi = 80; 來代替嗎?可以,這裏可以通過*pi修改i1的值。(第5行的註釋)*/
/* 請自行與前面一個例子比較。 */
printf("%d", *pi); /* 輸出是80 */
/* 代碼結束 */
語義分析:
看了這段代碼,你明白了什麼?有沒有發現pi值是不能重新賦值修改了。它只能永遠指向初始化時的內存地址了。相反,這次你可以通過*pi來修改i1的值了。與前一個例子對照一下吧!看以下的兩點分析:
1)pi因爲有了const 的修飾,所以只是一個指針常量:也就是說pi值是不可修改的(即pi不可以重新指向i2這個變量了)(請看第4行的註釋)。
2)整個*pi的前面沒有const 的修飾。也就是說,*pi是變量而不是常量,所以我們可以通過*pi來修改它所指內存i1的值(請看第5行的註釋)。
總之一句話,這次的pi是一個指向int變量類型數據的指針常量。
我最後總結兩句:
1) 如果const 修飾在*pi前,則不能改的是*pi(即不能類似這樣:*pi=50;賦值)而不是指pi。
2) 如果const 是直接寫在pi前,則pi不能改(即不能類似這樣:pi=&i;賦值)。

請你務必先記住這兩點,相信你一定不會再被它們給搞糊了。現在再看這兩個聲明語句int const *pi和int *const pi時,呵呵,你會頭昏腦脹還是很輕鬆愜意?它們各自聲明的pi分別能修改什麼,不能修改什麼?

二.其他情況

#include<iostream>
int main()
{
const int i1 = 40;
printf("i1=%d\n",i1); //40
int a=i1;
printf("a=%d\n",a); //40

int *pi;
pi = &i1;   //出錯
printf("%d\n",pi);  /*const int 類型的i1的地址是不能賦值給指向int 類型地址的指針pi的。否則pi豈不是能修改i1的值了嗎!*/


int a=1;
int *b;
b=&a;
printf("b=%d\n",*b); //1
a=2;
printf("b=%d\n",*b); //2
*b=3;
printf("a=%d\n",a); //3
return 0;
}


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