超详细!!!深入了解指针(2)

1.const修饰指针

1.1constr修饰变量

在前面文章提及关键字的时候讲到const可以修饰变量,函数。先来看看例子:

const具有常属性的意思,被他修饰的局部变量不可以被更改了(本质还是变量)。

但是如果我么绕过直接对a修改,利用他的地址找到并修改它呢?

可以看*pa绕过了const确实把a改了,但是我们用const修饰他不就是为了不被修改吗???

所以我们要对const的指针进行限制就可以避免这种情况。

1.2const 修饰指针变量

const修饰指针可以放在两个位置,一个是*前面,一个是*后面,他们的意义是不一样的。

1.2.1const放在*左边

*左边被const修饰的指针变量无法通过解引用去修改a,但是可以将自己的地址更改为&b。

举个例子:小美有个男朋友叫小帅,小帅兜里有100块钱,小美想要小帅请她吃饭,但是小帅就100块还有5天才发生活费,于是他就用const修饰了钱包,小美无法通过女朋友的身份去使用小帅的钱,但是她很聪明找到了舔狗小飞,把自己的眉眼抛给了小飞,但是小飞的钱包没有被const修饰,一下子就给了小美钱。

1.2.2const放在*右边

const放在*右边,是对这个指针本身的修饰,指针不能被修改了,就相当于小美不能去拿小帅的钱包,只能跟小帅绑在一起。但是他这时候可以动小帅的钱。

1.2.3const放在*两边

const放在*两边那可厉害了,被他修饰就相当于你既不能改变指向的对象,亦不能更改你本身的内容。

结论:const修饰指针变量的时候
const如果放在*的左边,修饰的是指针指向的内容,保证指针指向的内容不能通过指针来改变。
但是指针变量本⾝的内容可变。
const如果放在*的右边,修饰的是指针变量本⾝,保证了指针变量的内容不能修改,但是指针指
向的内容,可以通过指针改变。

2.野指针

野指针就是指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)

2.1野指针成因

1.指针未初始化:

我们知道局部变量是在栈上创建的,未初始化它是一个随机值,指针也是同理。

随机值就意味着他指向的地址可能是未被申请,还是属于操作系统,造成非法访问。

2,指针越界访问:
当指针超出了arr的范围就成了野指针。
3. 指针指向的空间释放:

2.2如何规避野指针

2.2.1指针初始化

当指针在创建的时候没有明确指向,可以先给它赋值NULL(C语言的一个标识符常量),它的值是0,0也是地址,不过需要注意,这个地址是无法使用的,使用会报错。

2.2.2防止指针越界

⼀个程序向内存申请了哪些空间,通过指针也就只能访问哪些空间,不能超出范围访问,超出了就是 越界访问

2.2.3指针变量不再使⽤时,及时置NULL,指针使用之前检查有效性

当指针变量指向⼀块区域的时候,我们可以通过指针访问该区域,后期不再使⽤这个指针访问空间的 时候,我们可以把该指针置为NULL。因为约定俗成的⼀个规则就是:只要是NULL指针就不去访问, 同时使⽤指针之前可以判断指针是否为NULL。

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

就是不要造成上面的那个错误三。

3.assert 断言

assert.h 头⽂件定义了宏 assert() ,⽤于在运⾏时确保程序符合指定条件,如果不符合,就报
错终⽌运⾏。这个宏常常被称为“断⾔”。
assert(),表达式的返回值为真,他不会产尘任何影响,但如果表达式为假,但会终止程序,并将报错位置给你写出来,功能还是很强大的
它的强大不仅如此,你还可以在不想使用assert的时候关闭它,在#include<assert.h>前面加上#define NDEBUG
assert的缺点是因为加入了额外的检查,会增加程序的运行时间。
一般我们在DEBUGB版本中使用,在release版本中禁用, ,在 VS 这样的集成开 发环境中,在 Release 版本中,直接就是优化掉了。这样在debug版本写有利于程序员排查问题,release版本有利于发布。

4.指针的使用和传址调用

4.1strlen的模拟实现

前面我们用指针相减模拟实现了my_strlen

现在根据它的原型来实现:size_t strlen ( const char * str );

参数str接收⼀个字符串的起始地址,然后开始统计字符串中 \0 之前的字符个数,最终返回⻓度。
如果要模拟实现只要从起始地址开始向后逐个字符的遍历,只要不是 \0 字符,计数器就+1,这样直到 \0 就停止

4.2指针的传值调用和传址调用

例如:写⼀个函数,交换两个整型变量的值
之前我们也写过,如果仅仅把两个变量的值传给函数(传值调用),他们是不会交换的,交换的仅仅是形参,所以那时候我们说形参是实参的 一份临时拷贝,对形参的修改不会改变实参,所以在传参的时候我们干脆就把指针传过去。
这就是函数的传址调用:
传址调⽤,可以让函数和主调函数之间建⽴真正的联系,在函数内部可以修改主调函数中的变量;所 以未来函数中只是需要主调函数中的变量值来实现计算,就可以采⽤传值调⽤。如果函数内部要修改主调函数中的变量的值,就需要传址调用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值