指针初阶二
- 野指针
野指针成因
如何避免野指针- 野指针概念
指的是指针指向的位置是不可知的(随机的,不正确的,没有明确限制的)大街上的野狗
- 野指针的成因
- 没有对指针初始化
{int* p;p是一个局部的指针变量,局部变量不初始化的话,默认是随机值
p现在放的是随机值
当我们对指针进行解引用的话,通过对p里存的随机的地址在内存找了一块由它指向的内存空间,这个空间是不是属不属于我们空间的呢?不是
*p = 20;那个地址指向的空间可能不是你的,非法访问内存
在这里的p就被称为野指针
运行起来不让你运行,用都不让你用
注意:内存里的是你申请了的,分给你的空间才叫你的空间
就像有个宾馆,我就睡觉了,他不属于你的,要掏钱
}
- 指针越界访问
int arr [10] = {0};
int* p = arr;
int i =0 ;
for()循环十次
*p = i;
p++
这个数组有是个元素
数组名交给指针变量p
p现在指向这个地方没大问题
现在循环十一次
你去解引用的时候越界然后解引用,这个p就是野指针
- 指针指向的空间释放
这个空间是你的,也申请好了,然后你也知道地址是啥
但是后来空间释放了,不属于你了空间还给操作系统
但地址你还记着
这个时候你再通过指针访问这个空间,不行
我还回去,p记住了,但是去用不行
就像你找个女朋友,后来有一天生气分手了
你再打电话就是骚扰比喻
退房以后再去住就是不行的
- 空间释放的详解
这个代码有没有问题呢?
首先调用test函数
有个局部变量a
当我们进入test函数
a这个局部变量被创建
这个空间创建后这块空间的地址0x1121434
return &a之后要返回
返回放到p里去
返回的时候把地址返回来
但是return&a以后返回去了a的变量周期到了
这个空间被销毁了,还给操作系统了
但是这个时候p还是存着这个地址0x1121434
这个时候*p=20 去访问的时候出问题
你说你还通过这个地址找到a的这个空间
放置成20;放也许是可以放的,但是这不属于你了,你还要强行放进去
这就非法访问内存了
因为a出test已经被销毁了
销毁是指把这四个字节的内容还给操作系统了
这个时候通过p存的地址去访问a不行的
这个p就是一个野指针
- 如何避免野指针
- 指针初始化
我们习惯每个变量都会初始化;
int a;
教材垃圾
编译器都不放过你
所以我们初始化
当然我们也要指针进行初始化
当前不知道p应该会初始化什么地址的时候,直接初识化空指针NULL
头文件include<stdio.h>
其实你会发现
#define NULL ((void *)0)
void*也是指针类型
把0强制类型转换成void *类型
但还是0
NULL就是0
你到路上遇到一条野狗,给他拴上一条链子,防止她乱害人
而现在这个p指针也一样,初识化空指针不要随便用它
//明确知道初识的值
int * ptr = &a ;
都叫初始化没问题
- 小心指针越界
C语言本身不会检查数据的越界类型的
- 指针指向的空间释放以后及时置成NULL(及时置空)
当我们一个指针指向的空间被释放了,那我们应该及时把这个指针置成空指针 int * = NULL;我们也不会去强行使用他了
- 指针使用之前检查有效性
比如我们及时初识化空指针我们也不能用它
这个地方 空指针不能使用
我们这有一个点
使用之前一定要检查有效性
if ( p ! = NULL)
* p = 10;
使用我们不知道这个指针指向哪时,把她初始化为空指针
当这个指针指向的空间被释放不用的时候,你也把这个指针置向空指针,当她指向有效空间的时候,你就给他一个有效的地址,这样的话,指针要么指向有效地址,要么指向空指针
使用之前先判断
用if,避免野指针的出现
- 指针初始化
- 没有对指针初始化
- 指针的运算
- 指针+-整数
图三:
指针关系运算
- 指针-指针
&arr [9] - &arr [0];
答案是多少呢验证一下
哎呦9
为什么是9,问题不大
这个数组放了十个地址
九个元素
指针-指针和我们所的是两个指针之间的元素个数
但有前提:必须两个指针指向同一块空间
我们现在灵活应用一下
strlen - 求字符串长度
头文件<string.h>
int len = strlen ("abc");
printf("%d",len);
结果是三
在讲函数的时候模拟实现了strlen
my_strlen计数器的方法实现(图三)
递归的时候还有一种方法
指针-指针
拿到a的地址 拿到/0的地址
还有一种版本指针-指针
图四
- 指针+-整数
- 野指针概念
指针初阶三
- 指针的关系运算
两种写法神仙打架
但有标准规定
图二中有标准规定
数组从0开始数的,不能数到-1 但可以从5数到6
从右向左不符合标准
- 指针与数组
- 数组名是什么
看例子:直接看打印真逗
数组名就是数组首元素的地址
我们就可以这样去理解[图二]
产生的就是下标为i这个元素的地址
图三是在访问数组
- 扩展
arr数组名是首元素地址
int * p = arr;
等价 交换律 无限套娃
可以呀
竟然没毛病
arr[2] p [2 ]
都是三关键在于这个操作符
C语言确实很灵活呀
- 二级指针
是什么:其实呀
套娃四级指针三级指针
但最常用的就是二级指针
- 指针数组
理解要有自己的认识
主语是什么? --数组
好孩子
指针数组到底是个怎样的数组呢?
int arr [10];//这是一个整形数组:--存放整形的数组就是整形数组
char ch [5];//字符数组 - --存放的是字符
指针数组 ---存放指针的数组
int * parr [5]; //整形指针的数组
整形指针数组
- 数组名是什么