初识指针
- 一.野指针
- 1.野指针形成原因一是:未初始化
- 2.野指针形成原因二:指针越界
- 3.野指针形成原因三:指针所指向的内存空间被释放
- 二.指针的运算
- 1.指针+-整数运算
- 2.指针-指针
- 3.指针的关系运算
- 三.指针和数组
- 四.二级指针
- 五.指针数组
- 1.定义
- 2.用一维数组来模拟二维数组
一.野指针
野指针就是指针指向的位置是不可知的(随机的,不正确的,没有明确限制的)
1.野指针形成原因一是:未初始化
当我这样写时,p是一个局部变量,没有初始化,那么p内就是一个随机值,那么编译器就会把这个随机值看作地址(某个内存单元编号),那么你解引用P,编译器就会找到这一个地址所对应的内存单元,将里面的数据变为20,但这种操作是很危险的,因为你根本不知道这个20存到了哪,你就无法找到它,相当于就白存了
像这种将a的地址存到p内,我们就可以准确找到这个地址所对应的内存单元,从而找到并使用这个内存单元内存的数据
2.野指针形成原因二:指针越界
这里arr数组内只有10个元素,但我却访问了11个元素,当我访问到了第11个元素时,就越界了,越界了会发生什么呢
它会产生一个随机值
3.野指针形成原因三:指针所指向的内存空间被释放
这里在创建a后我们向编译器申请了4个字节的内存,我们在完成函数test后,返回了一个a的地址,但在test函数结束后,编译器会销毁为test函数所创造的空间,所以你返回的地址所对应的内存实际上已经没有了,所以这个返回值无效
二.指针的运算
1.指针±整数运算
这里*p++其实由于解引用的优先级很低,所以其实是 * (p++),p++由于是整形,一次跳过4个字节,又由于arr类型是int,其中每个元素都是4个字节,所以+1相当于跳过一个元素,而我每跳过一个元素就把该元素改为0,故打印出来数组的元素全部为0
同理-1就是向前跳跃改指针所对应类型的字节大小
2.指针-指针
前提:两个指针得指向同一块空间
得到的是两个指针之间的元素个数
3.指针的关系运算
指针的大小比较实际上就是该指针所存的地址大小比较,就是那一串编号
三.指针和数组
数组是向编译器申请一块内存来存放数据
指针(变量)是用来存放地址,我们可以通过指针来访问数组
四.二级指针
这里我们设a=10,给a 4内存单元,每个内存单元都是1个字节,每个内存单元都有各自的编号,我们取出的是首字节编号,我们假设a的编号是如上图,pa内存的就是这个编号。
那么二级指针就是用来存放一级指针的地址
我们创造一个二级指针ppa,如果pa它的地址是如图,那么ppa内存的就是pa的地址
五.指针数组
1.定义
指针数组就是用来存放指针的数组
其实与整形,字符型数组一样都是用于存放数据
ps:这里插个小知识:我们访问数组内部的元素时都是使用下标如arr[0]。实际上,编译器会自动将这种写法改为 解引用(arr+0),因为arr代表首元素地址,+0就表示该数组第一个元素地址,再解引用就可以得到该元素。同理,arr[9]就是 解引用(arr+8)
2.用一维数组来模拟二维数组
如果我想创建一个3行4列的二维数组,那我们创造三个一维数组,以及一个指针数组
注意在这里a,b,c是数组的名字代表数组的首元素地址,我们用一个指针数组arr将a,b,c三个数组的首元素地址存起来,那么arr[0]就代表a数组的首元素地址,arr[1]就代表b数组的首元素地址,arr[2]就代表c数组的首元素地址。
这里arr[i][j]其实就是 * (arr[i]+j),那么我们就可以理解其实就是分别用每个数组的首元素地址+j再解引用,就可以把三个数组联系起来,从而得到一个二维数组