但凡涉及到和内存相关的知识时,老爹都会使用PPT绘制图形来辅助讲解。如果没有那些图的话,理解起来还是有一些困难。
「就然说到这里,就顺便提一下指针的自加和自减。我们先回顾一下普通变量的自加和自减:
int a = 10;
对于a++等效于a = a + 1,a--等效于a = a - 1。
那么对于指针变量
int* p =&a;
来说也是一样的
p++等效于p = p + 1,p--等效于p = p - 1。
而我们刚刚才说过,对指针做加减运算,实际上是按照指针指向的数据类型为单位上下移动,如果我们再配合*的话,也可以对数组进行赋值或者取值,你比如说:
int arr[5];
int* p = arr;
int i = sizeof(arr)/ sizeof(arr[0]);
while(i--> 0)
{
scanf(%d, p++);
}
注意这里面有个两个需要关注的地方,首先是老爹用sizeof来获取了一个数组占用内存的字节数,如果这个地方换成sizeof(p)话,只会得到p这个变量占用的内存字节数,这是指针和数组名的区别之一。
第二点,数组名是不可以做自加和自减操作的,不信你们可以把scanf函数中的p++换成a++,绝对会出错。」
虽然老爹无比笃定,但本着不「事不目见耳闻而臆断其有无」的原则,我尝试了一下,果然是报错了。
「那为什么会这样呢?」
「这个嘛,老爹也没有看到过C语言是如何管理数组的,但是老爹猜测,arr是一个被const修饰的指针,何以见得?如果我们对变量p进行如下修改,就会发现p也不能执行自加自减操作了。
int* const p = arr;」
「const会将一个变量变成常量,如果修饰一个指针是不是指针也变成了常量?」
一直都沉默不语的小弦子出声问道。
「的确是这样,和普通变量一样,一个指针变量被const修饰后就变成了一个指针常量,那么我们就只能为其初始化一次,就不能再修改这个指针指向的地址了。例如:
int a = 0;
int b = 1;
int* const p =&a;
p =&b;
在执行最后一行代码的时候肯定会出错,因为指针变量被const修饰,并且已经为其赋值为变量a的地址了,就不能再做修改,这个应该看得懂吧?」
见我和小弦子都点了点头,老爹又接着说道:「虽然p指向的地址是不能再修改的,但并不影响我们修改这个地址对应的变量的值。换句话说:
*p = 3;
*p = 4;
是不会出错的!」
「老爹你等等,我感觉有点绕了。」
我突然觉得画风转变得有点快,让人触不及防,怎么就一下子就听不明白了呢?
「这样啊,那我们来举个例子好好捋一捋这其中的道道。
假设哈,我是假设我们有一把万能钥匙,这把钥匙能够打开所有的保险箱。」
「哇哦,那样的话我们不是发财了么?那我们还编什么程啊,直接开个专业开保险柜的店不就好了么?但凡遇到找我们开保险柜的,都收百分之一的手续费,每天数毛爷爷手都得数抽筋。」
别的不说,我入戏的速度还是很快的,老爹刚刚才做完设定,我就快速想好了下面的剧情。
「你看不管是电视剧还是动漫,但凡那些坐拥宝物但是却没有对应守护宝物的实力,最终的下场一般都是家破人亡。」
就在这个时候,小弦子幽幽说道。他的声音就像是一盆冰水当头淋下,把我编织的美好幻想冻得支离破碎。
「这20后的小孩儿10岁都能知道这么多的东西么?」
老爹捂着额头,很是无语地看着我和小弦子。
「哎呀,老爹,现在都2032年了,6G技术都已经投入商用了,你的思想不能还停留在上个世界90年代撒。」
「别打岔,先听我把例子说完!」
趁着老爹看他自己电脑的时候,我偷偷地吐了吐舌头,还向他做了个鬼脸。
「好景不长,犹豫你保管不善,这把万能钥匙损坏了,到最后就只能打开一个保险柜咯。
我们姑且认为,这把钥匙就是一个指针变量,一开始它可以指向任何保险柜,但是在损坏后就只能打开那个唯一的保险柜了,这就和被const修饰了一样。
那么问题来了,难道因为钥匙只能打开唯一的保险柜了之后,咱们就不能修改保险柜里面的内容了么?」
「哦,原来是这个意思么?那我明白了。」
我若有所思的点了点头。
「明白了?」
「嗯~」
「真的明白了?」
「嗯~」
「咱们欢乐加倍,来看看以下四种情况:
int* const p;
int const* p;
const int* p;
int const* const p;」
「我勒个去,这个都是些什么鬼?」
看着投影仪上面的这四句代码,除了刚刚讲过的第一句以外,其他三句在刹那间让我进入懵逼状态。
一旁的小弦子也好不到哪里去,连举着的杯子都停在了嘴边,一时间忘记了喝水。
「跌倒了没?崩溃了没?」
看着我和小弦子的表情,三十多岁的老爹居然开始幸灾乐祸。看这样子,是要把他当年受过的虐转移到我们身上啊。
「哈哈,你们这表情就跟当年我参加二级考试遇到这道题时的表情一模一样,不瞒你们说,事后我认真的研究过,结果久了不用,很快就忘了。等到大学毕业找工作的时候,面试时我再次在此败下阵来。
后来我痛定思痛,终于总结出来了一个小技巧。」
「什么技巧啊?」
我眼睛瞬间就开始放光了,仿佛看到了绝世珍宝。
「好吧,那我就将老爹历经数载悟出的真谛传授于你们,希望你们能替老爹我发扬光大。
但凡遇到指针和const,咱们就把代码倒过来读,也就是从由往左读,遇到*就替换为『指向』二字。
按照这个规则,第一句读出来就是:p是一个常数,指向一个int类型。就然p是一个常量,那么它的值(指向的地址)是不能够改变的,但是被它指向的地址中的内容(保险柜中的内容)修改不受到限制。
那你们来试试后面的。」
「p是一个指向int型常量的变量……」
「对头,咱们来做一个你们最熟悉的缩句,最终的结果是……」
「p是一个变量。」
「冰狗,对了。既然p是一个指针变量,它指向的地址自然是可以改变的,但是它指向的是一个int型常量,所以*p = 5这种赋值操作肯定就不行了。」