你知道我們申明乙個變數時象這樣int i ;這個i是可能在它處重新變賦值的。如下:
int i=0;
i=20;//這裡重新賦值了
不過有一天我的程式可能需要這樣乙個變數(暫且稱它變數),在申明時就賦乙個初始值。之後我的程式在其它任何處都不會再去重新對它賦值。那我又應該怎麼辦呢?用const .
const int ic =20;
ic=40;//這樣是不可以的,編譯時是無法通過,因為我們不能對const 修飾的ic重新賦值的。
//這樣我們的程式就會更早更容易發現問題了。
有了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 const * 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=50;賦值)而不是指pi.
2) 如果const 是直接寫在pi前則pi不能改(即不能類似這樣:pi=&i;賦值)。
請你務必先記住這兩點,相信你一定不會再被它們給搞糊了。現在再看這兩個申明語句int const *pi和int * const pi時,呵呵,你會頭昏腦脹還是很輕鬆愜意?它們各自申明的pi分別能修改什麼,不能修改什麼?再問問自己,把你的理解告訴我吧,可以發帖也可以發到我的郵箱(我的郵箱[email protected])!我一定會答覆的。
3) 補充三種情況。
這裡,我再補充以下三種情況。其實只要上面的語義搞清楚了,這三種情況也就已經被包含了。不過作為三種具體的形式,我還是簡單提一下吧!
情況一:int * pi指標指向const int i常量的情況
//**********begin*****************
const int i1=40;
int *pi;
pi=&i1; //這樣可以嗎?不行,vc下是編譯錯。
//const int 型別的i1的位址是不能賦值給指向int 型別位址的指標pi的。否則pi豈不是能修改i1的值了嗎!
pi=(int* ) &i1; // 這樣可以嗎?強制型別轉換可是c所支援的。
//vc下編譯通過,但是仍不能通過*pi=80來修改i1的值。去試試吧!看看具體的怎樣。
//***********end***************
情況二:const int * pi指標指向const int i1的情況
//*********begin****************
const int i1=40;
const int * pi;
pi=&i1;//兩個型別相同,可以這樣賦值。很顯然,i1的值無論是通過pi還是i1都不能修改的。
//*********end*****************
情況三:用const int * const pi申明的指標
//***********begin****************
int i
const int * const pi=&i;//你能想象pi能夠作什麼操作嗎?pi值不能改,也不能通過pi修改i的值。因為不管是*pi還是pi都是const的。
//************end****************
下篇預告:函式引數的指標傳遞,值傳遞,引用傳遞 迷惑(以為a,b已經代替了x,y,對x,y的操作就是對a,b的操作了,這是乙個錯誤的觀點啊!)。
C 語言環境設定詳細講解
c 環境設定 本地環境設定 如果您想要設定 c 語言環境,您需要確保電腦上有以下兩款可用的軟體,文字編輯器和 c 編譯器。文字編輯器 這將用於輸入您的程式。文字編輯器包括 windows notepad os edit command brief epsilon emacs 和 vim vi。文字編...
C 模版類 詳細講解
直接先說一下模版類的定義 template 模版型別1,模版型別2.class 類名 乙個小示例如下 templateclass a t getdata 模版函式,返回型別為t的值 以上的模版函式是在類的內部定義的,如果我們要定義乙個定義在類外的類模版成員函式的話,我們應該將這樣的類模版成員函式定義...
C 委託的詳細講解
委託是c 中一種型別,它的作用相當於c語言中的函式指標,它定義了方法的型別,使得可以將方法當作另乙個方法的引數來進行傳遞,這種將方法動態地賦給引數的做法,可以避免在程式中大量使用if else switch 語句,同時使得程式具有更好的可擴充套件性。委託和類是同級別的,我們可以直接將delegate...