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