网瘾少年带你学指针(2)

在上一节中我们了解了指针的基本概念以及相关的运算,这次我们再来看看指针还有什么东西。

指针其实是一个很危险的东西,因为我们只要有一个指向某个数据的指针,那么我们就可以通过这个指针直接修改这个内存中的数据,有时候可能会修改掉我们不想让它动的数据,那么有没有什么方式能够预防或者防止?

1.const

1.1 const修饰变量

我们都知道,变量是可以被修改的,但是如果我们不想让这个变量被修改,那么我们能不能对这个变量添加一些限制,让它没那么容易被修改?那么 const 就站出来了。

1985240e910e4a8692ea52aeb61864c6.png

这里我们创建了两个变量n和m,其中n用 const 修饰,然后我们可以看到,在我试图去修改n的值时,程序显示出来了错误,这就说明有 const 修饰的变量的值是不能被直接改变的。

但是,道高一尺,魔高一丈。直接的不行,咱们来个借刀杀人,这里n的值不能被直接修改,咱们就间接的来,通过指针找到它的地址,直接通过它的地址改它。

e7196e41d6b242169807e564c9a331d9.png

可以看到就算n被const修饰了,我们依旧能通过指针来修改它。

所以说指针很危险,那难道我们就拿指针没办法吗,指针难道真的能为所欲为吗?

1.2 const 修饰指针变量

虽然但是,我们用const修饰变量能被指针修改,那我们要是直接修饰指针变量呢?

但是要是修饰指针变量就又有个问题,我们的const是放在 ‘ * ’ 的左边还是右边?

const int* pn = &n;
int* const pn = &n;

 事实上,这两种方式是有区别的。

当const放在 * 左边时,注意这里是 *左边,跟int没有关系,const放int左边还是右边没有影响。

我们知道 *pn 是对这个指针解引用,相等于 n,那不就相当于是const 修饰n,但是这次是直接修饰的内存,这样就不能直接通过内存去修改n的值,这样就能限制通过这个指针去修改n的值了。但是我们要是没有去修饰n的话,是可以直接修改n的值的。

329c6f13fb284c5ba861040687f31a22.png

 那可能会有人说,你这不限制了个寂寞吗,你要这么说的话,我想说确实,那它这么设计我也没办法啊。实际上我们运用指针更多的场景是在函数中,如果你不想让指针修改某个值,这是可以通过const来限制它,这是就算你在函数中直接修改那个值,对我们主函数的值也没有影响。

当const放在 * 右边时就是对这个指针变量的内容进行限制,因为它也是一个变量,它指向的地址也是可以变的,要死我们不想让它指向的地址发生变化,那么就可以将const放在*的右边,这样就改不了它指向的地址了。

04e775aa742c4091b442b8f2090f2789.png

可以看到,这里我想要将pn的地址改为空指针,结果就报错了。

当然,我们还可以将这个const在 * 的左右两边都放一个,这样的效果就是即不能通过指针来改变它所指向的值,也不可以改变指针指向的地址。

我们可以这样记忆 const在 *左边,就是修饰 *pn 那*pn的值就不能修改, const在 * 右边,就是修饰 pn,那pn的值就是不能改变的。

2.野指针

我们在创建指针变量时,一般都是在已经知道了想要这个指针指向什么地址,就是在创建之初就已经知道它的值,那么假设我们在创建的时候没有给指针赋值呢?就像在变量创建的时候没有给变量一个初始值一样,这时指针指向的地址也是一个未知值,这样的指针我们就叫它野指针。

2.1野指针的成因

2.1.1 指针未初始化

我们刚刚就以及提到过,当我们创建一个指针却不对它进行初始化,那么它里面的值是一个随机值,指向的是一个未知的空间,这样就导致这个指针变成一个野指针。

2.1.2指针越界访问

当我们通过指针去访问一个数组时,如果这个指针指向的范围超出了数组的范围,那么它就是一个野指针。

在上面的程序中,当i等于10,就已经超出数组arr的储存范围了,这时p就是一个野指针。

2.1.3指针指向的空间释放

我创建了一个函数,在函数内部创建了一个临时变量,但我们都知道,函数在结束时,函数内部的临时变量所在的空间会别释放掉 ,这是你再用一个指针去接收这个被释放的变量的地址,那么这个指针就变成了一个野指针了。

2.2 如何规避野指针

2.2.1指针初始化

既然不对指针进行初始化会导致野指针的产生,那么我们对指针进行初始化不就行了。

如果我们明确知道了这个指针要指向哪里,那么我们直接让这个指针能够完成任务就行,但是如果我们不知道要让它指向的具体位置呢?这时就可以像我们给别的数据初始化那样,将它初始化为0。

但是它是一个地址啊,肯定不能是初始化为0啊,这是C语言给我们提供了一个标识符NULL,它就等价于0,值是0,但是它是一个地址,我们不能对这个地址进行操作,不然会报错。

2.2.2 小心指针越界,以及指针的及时置空

当我们使用程序去访问内存时,一定要注意哪些内存是我们能够去使用的,哪些是不能去使用的,在访问内存时一定要小心。

当指针指向某一块区域时,我们通过指针去访问这个区域,在后期不需要再次访问的时侯,就可以把这个指针置空,避免使用使用时造成越界。

上面的程序中,在循环结束时,p就以及越界了,所以要及时置空。

2.2.3 避免返回局部变量的地址

就像我们刚刚举例造成野指针的原因一样,要避免返回局部变量的地址。 

  • 22
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值