常量指针与指针常量的区别(转帖)
轉(zhuǎn)載:http://www.cnblogs.com/witty/archive/2012/04/06/2435311.html
三個(gè)名詞雖然非常繞嘴,不過(guò)說(shuō)的非常準(zhǔn)確。用中國(guó)話的語(yǔ)義分析就可以很方便地把三個(gè)概念區(qū)分開(kāi)。
一) 常量指針。
常量是形容詞,指針是名詞,以指針為中心的一個(gè)偏正結(jié)構(gòu)短語(yǔ)。這樣看,常量指針本質(zhì)是指針,常量修飾它,表示這個(gè)指針乃是一個(gè)指向常量的指針(變量)。
指針指向的對(duì)象是常量,那么這個(gè)對(duì)象不能被更改。
在C/C++中,常量指針是這樣聲明的:
1)const int *p;
2)int const *p;
常量指針的使用要注意,指針指向的對(duì)象不能通過(guò)這個(gè)指針來(lái)修改,可是仍然可以通過(guò)原來(lái)的聲明修改,也就是說(shuō)常量指針可以被賦值為變量的地址,之所以叫做常量指針,是限制了通過(guò)這個(gè)指針修改變量的值。例如:
int a = 5;
const int b = 8;
? const int *c = &a; // 這是合法的,非法的是對(duì)c的使用
*c = 6; // 非法,但可以這樣修改c指向的對(duì)象的值:a = 6;
const int *d = &b; // b是常量,d可以指向b,d被賦值為b的地址是合法的
? 細(xì)心的朋友在使用字符串處理函數(shù)的時(shí)候,應(yīng)該會(huì)注意到這些函數(shù)的聲明。它們的參數(shù)一般聲明為常量指針。例如,字符串比較函數(shù)的聲明是這樣的:
int strcmp(const char *str1, const char *str2);
可是這個(gè)函數(shù)卻可以接收非常量字符串。例如這段程序:
char *str1, *str2;
str1 = "abcde1234";
str2 = "bcde";
if(strcmp(str1, str2) == 0)
{
printf("str1 equals str2.");
}
str1和str2的內(nèi)容顯然是可以更改的,例如可以使用“str1[0] = x;”這樣的語(yǔ)句把str1的內(nèi)容由“abcde1234”變?yōu)椤皒bcde1234”。因?yàn)楹瘮?shù)的參數(shù)聲明用了常量指針的形式,就保證了在函數(shù)內(nèi)部,那 個(gè)常量不被更改。也就是說(shuō),對(duì)str1和str2的內(nèi)容更改的操作在函數(shù)內(nèi)部是不被允許的。(就目前的應(yīng)用來(lái)看,我覺(jué)得設(shè)置常量指針就是為函數(shù)參數(shù)聲明準(zhǔn) 備的,不然還真不知道用在什么地方呢,呵呵!)
雖然常量指針指向的對(duì)象不能變化,可是因?yàn)槌A恐羔樖且粋€(gè)變量,因此,常量指針可以不被賦初始值,且可以被重新賦值。例如:
const int a = 12;
const int b = 15;
const int *c = &a; // 為了簡(jiǎn)化代碼,很多人習(xí)慣賦初始值
const int *d;
d = &a; // 這樣當(dāng)然是可以的
c = &b; // 雖然c已經(jīng)被賦予初始值,可是仍然可以指向另一個(gè)變量
特點(diǎn)是,const的位置在指針聲明運(yùn)算符*的左側(cè)。只要const位于*的左側(cè),無(wú)論它在類型名的左邊或右邊,都聲明了一個(gè)指向常量的指針,叫做常量指針。
可以這么想,*左側(cè)是常量,指針指向的對(duì)象是常量。
二) 指針常量
指針是形容詞,常量是名詞。這回是以常量為中心的一個(gè)偏正結(jié)構(gòu)短語(yǔ)。那么,指針常量的本質(zhì)是一個(gè)常量,而用指針修飾它,那么說(shuō)明這個(gè)常量的值應(yīng)該是一個(gè)指針。
指針常量的值是指針,這個(gè)值因?yàn)槭浅A?#xff0c;所以不能被賦值。
在C/C++中,指針常量這樣聲明:
int a;
int *const b = &a; //const放在指針聲明操作符的右側(cè)
只要const位于指針聲明操作符右側(cè),就表明聲明的對(duì)象是一個(gè)常量,且它的內(nèi)容是一個(gè)指針,也就是一個(gè)地址。上面的聲明可以這么讀,聲明了一個(gè)常量b,它的值是變量a的地址(變量a的地址,不就是指向變量a的指針嗎)。
因?yàn)橹羔槼A渴且粋€(gè)常量,在聲明的時(shí)候一定要給它賦初始值。一旦賦值,以后這個(gè)常量再也不能指向別的地址。
雖然指針常量的值不能變,可是它指向的對(duì)象是可變的,因?yàn)槲覀儾](méi)有限制它指向的對(duì)象是常量。
因此,有這么段程序:
char *a = "abcde1234";
char *b = "bcde";
char *const c = &a;
? 下面的操作是可以的。
? a[0] = 'x'; // 我們并沒(méi)有限制a為常量指針(指向常量的指針)
或者
*c[0] = 'x' // 與上面的操作一致
三)指向常量的指針常量
顧名思議,指向常量的指針常量就是一個(gè)常量,且它指向的對(duì)象也是一個(gè)常量。
因?yàn)槭且粋€(gè)指針常量,那么它指向的對(duì)象當(dāng)然是一個(gè)指針對(duì)象,而它又指向常量,說(shuō)明它指向的對(duì)象不能變化。
在C/C++中,這么聲明:
? const int a = 25;
const int * const b = &a;
看,指針聲明操作符左邊有一個(gè)const,說(shuō)明聲明的是一個(gè)指向常量的指針。再看,指針聲明操作符右邊有一個(gè)const,說(shuō)明聲明的是一個(gè)指針常量。前后都鎖死了,那么指向的對(duì)象不能變,指針常量本身也不能變。細(xì)細(xì)體味,相信能得其道,下面就不贅述了。
用一個(gè)例子作為總結(jié)。雖然字符指針與其它指針的本質(zhì)是一樣的,可是因?yàn)樽址羔槼S脕?lái)表示字符串,常不好理解。下面就用字符指針來(lái)舉例。
char *a = "abcde1234";
const char *b = "bcde"; // b是指向常量字符串的指針變量
char *const c = &a;? // c是指向字符指針變量的常量
const char *const d = &b; // d是指向字符常量的指針常量
問(wèn)題來(lái)了。
1)問(wèn):因?yàn)閍是變量,a可以賦值為其它值,如"12345abc"。那么c指向a,當(dāng)a變化了,c指向什么呢?
答:仍然指向"abcde1234"。雖然a可以指向別的字符串,可是c仍然指向"abcde1234",也就是a開(kāi)始指向的對(duì)象。
2)問(wèn):a是變量,可以改變a的內(nèi)容。那么當(dāng)執(zhí)行了“a[0] = 'x';”后,c會(huì)怎樣呢?
答:c當(dāng)然還指向a初始指向的字符。不過(guò),這個(gè)字符已經(jīng)變成了'x'。
3)問(wèn):b是指向常量的指針變量,當(dāng)b指向別的字符串,d怎么樣?
答:d仍然指向b初始的字符串。
4)問(wèn):b可以變化,b指向的字符不能變化,也就是說(shuō)b[0]不能被重新賦值,可是b[1]可以被重新賦值嗎?
答:原則上b指向的字符是常量,并沒(méi)有限制下一個(gè)字符,應(yīng)該可以被賦值。可是因?yàn)槟闶褂米址M(jìn)行了初始賦值,而且編譯器是靜態(tài)編譯的,C/C++程序就把b當(dāng)作字符串指針來(lái)處理了,因此,當(dāng)對(duì)下一個(gè)字符進(jìn)行賦值時(shí),編譯不能通過(guò)。
其他問(wèn)題,歡迎補(bǔ)充。
我編了這樣的口訣,記住,應(yīng)該不難:
const(*號(hào))左邊放,我是指針變量指向常量;
const(*號(hào))右邊放,我是指針常量指向變量;
const(*號(hào))兩邊放,我是指針常量指向常量;
指針變量能改指向,指針常量不能轉(zhuǎn)向!
要是全都變成常量,鎖死了,我不能轉(zhuǎn)向,你也甭想變樣!
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)
總結(jié)
以上是生活随笔為你收集整理的常量指针与指针常量的区别(转帖)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: exec函数族实例解析
- 下一篇: 智能指针学习笔记