第四十九章 指針(四)
但凡涉及到和內(nèi)存相關(guān)的知識(shí)時(shí),老爹都會(huì)使用PPT繪制圖形來(lái)輔助講解。如果沒(méi)有那些圖的話,理解起來(lái)還是有一些困難。
「就然說(shuō)到這里,就順便提一下指針的自加和自減。我們先回顧一下普通變量的自加和自減:
int a = 10;
對(duì)于a++等效于a = a + 1,a--等效于a = a - 1。
那么對(duì)于指針變量
int* p =&a;
來(lái)說(shuō)也是一樣的
p++等效于p = p + 1,p--等效于p = p - 1。
而我們剛剛才說(shuō)過(guò),對(duì)指針做加減運(yùn)算,實(shí)際上是按照指針指向的數(shù)據(jù)類(lèi)型為單位上下移動(dòng),如果我們?cè)倥浜?的話,也可以對(duì)數(shù)組進(jìn)行賦值或者取值,你比如說(shuō):
int arr[5];
int* p = arr;
int i = sizeof(arr)/ sizeof(arr[0]);
while(i--> 0)
{
scanf(%d, p++);
}
注意這里面有個(gè)兩個(gè)需要關(guān)注的地方,首先是老爹用sizeof來(lái)獲取了一個(gè)數(shù)組占用內(nèi)存的字節(jié)數(shù),如果這個(gè)地方換成sizeof(p)話,只會(huì)得到p這個(gè)變量占用的內(nèi)存字節(jié)數(shù),這是指針和數(shù)組名的區(qū)別之一。
第二點(diǎn),數(shù)組名是不可以做自加和自減操作的,不信你們可以把scanf函數(shù)中的p++換成a++,絕對(duì)會(huì)出錯(cuò)?!?p> 雖然老爹無(wú)比篤定,但本著不「事不目見(jiàn)耳聞而臆斷其有無(wú)」的原則,我嘗試了一下,果然是報(bào)錯(cuò)了。
「那為什么會(huì)這樣呢?」
「這個(gè)嘛,老爹也沒(méi)有看到過(guò)C語(yǔ)言是如何管理數(shù)組的,但是老爹猜測(cè),arr是一個(gè)被const修飾的指針,何以見(jiàn)得?如果我們對(duì)變量p進(jìn)行如下修改,就會(huì)發(fā)現(xiàn)p也不能執(zhí)行自加自減操作了。
int* const p = arr;」
「const會(huì)將一個(gè)變量變成常量,如果修飾一個(gè)指針是不是指針也變成了常量?」
一直都沉默不語(yǔ)的小弦子出聲問(wèn)道。
「的確是這樣,和普通變量一樣,一個(gè)指針變量被const修飾后就變成了一個(gè)指針常量,那么我們就只能為其初始化一次,就不能再修改這個(gè)指針指向的地址了。例如:
int a = 0;
int b = 1;
int* const p =&a;
p =&b;
在執(zhí)行最后一行代碼的時(shí)候肯定會(huì)出錯(cuò),因?yàn)橹羔樧兞勘籧onst修飾,并且已經(jīng)為其賦值為變量a的地址了,就不能再做修改,這個(gè)應(yīng)該看得懂吧?」
見(jiàn)我和小弦子都點(diǎn)了點(diǎn)頭,老爹又接著說(shuō)道:「雖然p指向的地址是不能再修改的,但并不影響我們修改這個(gè)地址對(duì)應(yīng)的變量的值。換句話說(shuō):
*p = 3;
*p = 4;
是不會(huì)出錯(cuò)的!」
「老爹你等等,我感覺(jué)有點(diǎn)繞了?!?p> 我突然覺(jué)得畫(huà)風(fēng)轉(zhuǎn)變得有點(diǎn)快,讓人觸不及防,怎么就一下子就聽(tīng)不明白了呢?
「這樣啊,那我們來(lái)舉個(gè)例子好好捋一捋這其中的道道。
假設(shè)哈,我是假設(shè)我們有一把萬(wàn)能鑰匙,這把鑰匙能夠打開(kāi)所有的保險(xiǎn)箱?!?p> 「哇哦,那樣的話我們不是發(fā)財(cái)了么?那我們還編什么程啊,直接開(kāi)個(gè)專(zhuān)業(yè)開(kāi)保險(xiǎn)柜的店不就好了么?但凡遇到找我們開(kāi)保險(xiǎn)柜的,都收百分之一的手續(xù)費(fèi),每天數(shù)毛爺爺手都得數(shù)抽筋?!?p> 別的不說(shuō),我入戲的速度還是很快的,老爹剛剛才做完設(shè)定,我就快速想好了下面的劇情。
「你看不管是電視劇還是動(dòng)漫,但凡那些坐擁寶物但是卻沒(méi)有對(duì)應(yīng)守護(hù)寶物的實(shí)力,最終的下場(chǎng)一般都是家破人亡。」
就在這個(gè)時(shí)候,小弦子幽幽說(shuō)道。他的聲音就像是一盆冰水當(dāng)頭淋下,把我編織的美好幻想凍得支離破碎。
「這20后的小孩兒10歲都能知道這么多的東西么?」
老爹捂著額頭,很是無(wú)語(yǔ)地看著我和小弦子。
「哎呀,老爹,現(xiàn)在都2032年了,6G技術(shù)都已經(jīng)投入商用了,你的思想不能還停留在上個(gè)世界90年代撒?!?p> 「別打岔,先聽(tīng)我把例子說(shuō)完!」
趁著老爹看他自己電腦的時(shí)候,我偷偷地吐了吐舌頭,還向他做了個(gè)鬼臉。
「好景不長(zhǎng),猶豫你保管不善,這把萬(wàn)能鑰匙損壞了,到最后就只能打開(kāi)一個(gè)保險(xiǎn)柜咯。
我們姑且認(rèn)為,這把鑰匙就是一個(gè)指針變量,一開(kāi)始它可以指向任何保險(xiǎn)柜,但是在損壞后就只能打開(kāi)那個(gè)唯一的保險(xiǎn)柜了,這就和被const修飾了一樣。
那么問(wèn)題來(lái)了,難道因?yàn)殍€匙只能打開(kāi)唯一的保險(xiǎn)柜了之后,咱們就不能修改保險(xiǎn)柜里面的內(nèi)容了么?」
「哦,原來(lái)是這個(gè)意思么?那我明白了?!?p> 我若有所思的點(diǎn)了點(diǎn)頭。
「明白了?」
「嗯~」
「真的明白了?」
「嗯~」
「咱們歡樂(lè)加倍,來(lái)看看以下四種情況:
int* const p;
int const* p;
const int* p;
int const* const p;」
「我勒個(gè)去,這個(gè)都是些什么鬼?」
看著投影儀上面的這四句代碼,除了剛剛講過(guò)的第一句以外,其他三句在剎那間讓我進(jìn)入懵逼狀態(tài)。
一旁的小弦子也好不到哪里去,連舉著的杯子都停在了嘴邊,一時(shí)間忘記了喝水。
「跌倒了沒(méi)?崩潰了沒(méi)?」
看著我和小弦子的表情,三十多歲的老爹居然開(kāi)始幸災(zāi)樂(lè)禍??催@樣子,是要把他當(dāng)年受過(guò)的虐轉(zhuǎn)移到我們身上啊。
「哈哈,你們這表情就跟當(dāng)年我參加二級(jí)考試遇到這道題時(shí)的表情一模一樣,不瞞你們說(shuō),事后我認(rèn)真的研究過(guò),結(jié)果久了不用,很快就忘了。等到大學(xué)畢業(yè)找工作的時(shí)候,面試時(shí)我再次在此敗下陣來(lái)。
后來(lái)我痛定思痛,終于總結(jié)出來(lái)了一個(gè)小技巧?!?p> 「什么技巧啊?」
我眼睛瞬間就開(kāi)始放光了,仿佛看到了絕世珍寶。
「好吧,那我就將老爹歷經(jīng)數(shù)載悟出的真諦傳授于你們,希望你們能替老爹我發(fā)揚(yáng)光大。
但凡遇到指針和const,咱們就把代碼倒過(guò)來(lái)讀,也就是從由往左讀,遇到*就替換為『指向』二字。
按照這個(gè)規(guī)則,第一句讀出來(lái)就是:p是一個(gè)常數(shù),指向一個(gè)int類(lèi)型。就然p是一個(gè)常量,那么它的值(指向的地址)是不能夠改變的,但是被它指向的地址中的內(nèi)容(保險(xiǎn)柜中的內(nèi)容)修改不受到限制。
那你們來(lái)試試后面的?!?p> 「p是一個(gè)指向int型常量的變量……」
「對(duì)頭,咱們來(lái)做一個(gè)你們最熟悉的縮句,最終的結(jié)果是……」
「p是一個(gè)變量?!?p> 「冰狗,對(duì)了。既然p是一個(gè)指針變量,它指向的地址自然是可以改變的,但是它指向的是一個(gè)int型常量,所以*p = 5這種賦值操作肯定就不行了。」