天天看點

const int *p,const * int p,int const *p

從微軟的一道面試題談起

5.What is the output of the follow code?

voidmain(int argc, char* argv[]) {

int i = 11;

int const *p = &i;

p++;

print(“%d”,*p);

}

A. 11 B. 12 C.Garbage value D. Comipler error E. None of above

Choose:C

const int *p,const * int p,int const *p

1 從const int i 說起

有了const修飾的ic 我們不稱它為變量,而稱符号常量,代表着20這個數。這就是const 的作用。ic是不能在它處重新賦新值了。

認識了const 作用之後,另外,我們還要知道格式的寫法。有兩種:const int ic=20;與int const ic=20;。它們是完全相同的。這一點我們是要清楚。總之,你務必要記住const 與int哪個寫前都不影響語義。有了這個概念後,我們來看這兩個家夥:const int * pi與int const * pi ,按你的邏輯看,它們的語義有不同嗎?呵呵,你隻要記住一點,int 與const 哪個放前哪個放後都是一樣的,就好比const int ic;與int const ic;一樣。也就是說,它們是相同的。

好了,我們現在已經搞定一個“雙包胎”的問題。那麼int * const pi與前兩個式子又有什麼不同呢?我下面就來具體分析它們的格式與語義吧!

2 const int * pi的語義

我先來說說const int * pi是什麼作用。看下面的例子:

int i1=30;

int i2=40;

const int * pi=&i1;

pi=&i2; //4.注意這裡,pi可以在任意時候重新指派一個新記憶體位址

i2=80; //5.想想看:這裡能用*pi=80;來代替嗎?當然不能

printf( “%d”, *pi ) ; //6.輸出是80

語義分析:

看出來了沒有啊,pi的值是可以被修改的。即它可以重新指向另一個位址的,但是,不能通過*pi來修改i2的值。這個規則符合我們前面所講的邏輯嗎?當然符合了!

首先const 修飾的是整個*pi(注意,我寫的是*pi而不是pi)。是以*pi是常量,是不能被指派的(雖然pi所指的i2是變量,不是常量)。

其次,pi前并沒有用const 修飾,是以pi是指針變量,能被指派重新指向另一記憶體位址的。你可能會疑問:那我又如何用const 來修飾pi呢?其實,你注意到int * const pi中const 的位置就大概可以明白了。請記住,通過格式看語義。

3 再看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; 4.注意這裡,pi不能再這樣重新指派了,即不能再指向另一個新位址。

//是以我已經注釋了它。

i1=80; //5.想想看:這裡能用*pi=80;來代替嗎?可以,這裡可以通過*pi修改i1的值。

//請自行與前面一個例子比較。

printf( “%d”, *pi ) ; //6.輸出是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。

2).如果const 是直接寫在pi前則pi不能改。

3.補充三種情況。

這裡,我再補充以下三種情況。其實隻要上面的語義搞清楚了,這三種情況也就已經被包含了。不過作為三種具體的形式,我還是簡單提一下吧!

情況一:int * pi指針指向const int i常量的情況

const int i1=40;

int *pi;

pi=&i1;//這樣可以嗎?不行,VC下是編譯錯。

//const int 類型的i1的位址是不能指派給指向int 類型位址的指針pi的。否則pi豈不是能修改i1的值了嗎!

pi=(int* ) &i1;  // 這樣可以嗎?強制類型轉換可是C所支援的。

//VC下編譯通過,但是仍不能通過*pi=80來修改i1的值。去試試吧!看看具體的怎樣。

情況二:const int * pi指針指向const int i1的情況

const int i1=40;

const int * pi;

pi=&i1;//兩個類型相同,可以這樣指派。很顯然,i1的值無論是通過pi還是i1都不能修改的。