1. 程式人生 > >指針和引用(2)指針常量與常量指針

指針和引用(2)指針常量與常量指針

知識點 getc 什麽 TE 歷史 語句 return tchar 面試

1.知識點

1.1指針常量——指針類型的常量

(1)指針常量本質是常量,指針用來說明常量的類型,表示該常量是一個指針類型的常量。

(2)在指針常量中,指針的值不可變,即始終指向同一個地址。

(3)但指針所指向的地址的值是可以通過*p來改變的。

用法如下:

1 //技巧:
2 //(1)讀法:從左到右讀,前面的是修飾詞,後面的是主語
3 //如先出現指針(*),後出現常量(const),所以是指針常量
4 //(2)哪個東西不可變:直接看const後邊是什麽就什麽不可變
5 //const後邊是指針(p),所以是指針本身的值不可變。
6 int a = 10, b = 20;
7 int * const p = &a;
8 *p = 30;

1.2常量指針——指向常量的指針

(1)常量指針本質上是一個指針,常量表示指針指向的內容,說明指針指向的是一個“常量”。

(2)在常量指針中,指針指向的內容是不可變的,不可以通過*p來改變,但變量(指針指向的地址)可以通過自身賦值改變。

(3)另指針指向的地址是可以變的,即指向其他地址。

用法如下:

1 //技巧:
2 //(1)讀法:從左到右讀,前面的是修飾詞,後面的是主語
3 //如下先出現常量(const),然後出現指針(*),所以是常量指針
4 //(2)哪個東西不可變:直接看const後邊是什麽就什麽不可變
5 //如下const後面是*p,所以是指針指向的地址的值不可變(只限定了不可以通過*p來改變)
6 int a = 10, b = 20; 7 int const *p = &a;//不可以通過*p改變a的值 8 p = &b;//指針的地址是可以變的 9 a = 30;//也可以通過變量本身改變值

1.3const int 與int consts是等價的

const int *p==int const *p

2.面試題

2.1指針常量和常量指針的常見錯誤

 1 int main(int argc, char *argv[]) {
 2     int m = 10;
 3     const int n = 20;
 4     
 5     const int *ptr1 = &m;
6 int * const ptr2 = &m; 7 8 ptr1 = &n; 9 ptr2 = &n; 10 11 *ptr1 = 3; 12 *ptr2 = 4; 13 14 int *ptr3 = &n; 15 const int *ptr4 = &n; 16 17 int *const ptr5; 18 ptr5 = &m; 19 20 const int * const ptr6 = &m; 21 *ptr6 = 5; 22 ptr6 = &n; 23 24 getchar(); 25 return 0; 26 }

答案解析:

 1 int main(int argc, char *argv[]) {
 2     int m = 10;    //正確,變量
 3     const int n = 20;    //正確,常量
 4     
 5     const int *ptr1 = &m;    //正確,常量指針,指向的地址的內容不可變
 6     int * const ptr2 = &m;    //正確,指針常量,指針指向不可變,是常量所以必須賦初值
 7 
 8     ptr1 = &n;//正確
 9     ptr2 = &n;//錯誤,指針常量,指針的指向不可變
10 
11     *ptr1 = 3;//錯誤,常量指針,指針指向的地址的內容不可變
12     *ptr2 = 4;//正確
13 
14     int *ptr3 = &n;//錯誤,不能將常量的地址賦值給普通指針,常量地址只能賦值給常量指針
15     const int *ptr4 = &n;//正確
16 
17     int *const ptr5;//錯誤,指針常量是常量,所有常量在定義時都必須賦初值
18     ptr5 = &m;//錯誤,應該定義時直接賦初值
19 
20     const int * const ptr6 = &m;//正確,同時包含指針常量和常量指針的性質
21     *ptr6 = 5;//錯誤,不符合常量指針的性質
22     ptr6 = &n;//錯誤,不符合指針常量的性質
23     getchar();
24     return 0;
25 }

2.2指針常量用作函數參數

寫出程序的輸出結果,並說明在函數exchange2中將參數聲明為const的意義,是否可以將const修飾符放在*之前。

 1 void exchange1(int a, int b) {
 2     int temp = a;
 3     a = b;
 4     b = temp;
 5 }
 6 void exchange2(int * const a, int * const b) {
 7     int temp = *a;
 8     *a = *b;
 9     *b = temp;
10 }
11 int main(int argc, char *argv[]) {
12     int m = 10, n = 20;
13     exchange1(m, n);
14     cout << "m=" << m << ";n=" << n << endl;  //輸出:m=10;n=20
15     exchange2(&m, &n);
16     cout << "m=" << m << ";n=" << n << endl;  //輸出:m=20,n=10
17     getchar();
18     return 0;
19 }

答案:第一行輸出的是:m=10,n=20;第二行輸出是:m=20,n=10.

解析:exchange1按值傳遞,函數中a,b值交換與m,n無任何聯系,故無法改變m,n的值;exchange2中傳入m,n的地址,通過解引用可以在函數內部改變m,n的值。在函數exhange2的參數中,const的作用是將指針聲明為指針常量,防止指針a和b在使用過程中意外發生改變(改變將會報錯)。如果將const放在*之前,指針a和b變成常量指針,無法修改指針指向的內容,從而無法實現交換m和n的目的。

2.3指針常量和字符串常量的沖突

請寫出下面程序的運行結果:

1 int main(){
2   char *const str="apple";
3   *str="orange";
4   cout<<str<<endl;
5   getchar();
6   return 0;          
7 }

答案1(其實有問題,看下面說明,):

 int main(){
   char *const str="apple"; //錯誤,為了修改str的值應該去掉const
   *str="orange";//錯誤,根據字符串賦值規則應該改為str="orange"
   cout<<str<<endl;
   getchar();
   return 0;          
 }

說明:(1)一個字符串返回的是首字母的地址,故*str的值為‘a‘.

(2)字符串常量是存儲在常量區,而常量的值不可以修改,所以在VC編譯器中下面的語句是編譯不過去的

char *str = "apple";

最正確的語句應該是(因為字符串常量本身是常量,不應該賦值給一個普通指針,這意味著通過指針可以改變常量的值,前後矛盾,上面語句在一些地方能通過編譯,其實是由於歷史遺留問題):

const char *str = "apple";

(3)字符串正確賦值給變量應該是給str,因為字符串返回的其實是字符串的首地址,所以應該賦值給指針str,而不是*str,該指針指向首地址。

綜上最正確的答案應該如下:

1  int main(){
2    const char *str = "apple";//常量指針,指向的內容不可變
3    str = "oragne";//指針的指向是可變的
4    cout<<str<<endl;
5    getchar();
6    return 0;          
7  }

指針和引用(2)指針常量與常量指針