初级指针
一.指针是什么?
(指针就是个变量,变量里存的是内存单元的地址)
1.内存
2.代码
3.地址
4.总结
二.指针和指针类型
1.指针类型的大小
指针类型大小在32位操作系统是4个字节,在64位操作系统是8个字节,虽然他们大小相同,但都具有各自的实际意义,下面来探讨一下。
2.指针的实际意义
①指针的解引用
可以看出不管是什么类型的指针,都可以很好的把a的地址存起来,但因为a的地址是int型,此处会报警告,但仍可以把地址存起来。
接下来我们在窗口监视a的地址,让指针pa的地址变为0
(此时内存是倒着存放的,这里我们先不作讲解)
然后我们下一步,看a的地址如何变化
可以明显看出,a的地址全部变为0。实际是a的地址存在指针pa里,指针pa为0后,a的地址变为0。
下面再看一下字符指针
在窗口里监视a的地址,运行后观察地址变化
由此可以看出,指针有自己的意义,虽然都可以存放地址,但是在进行解引用时有自己的特点。即指针类型决定了指针进行解引用操作时,能够访问空间的大小。(访问字节的大小)
②指针±整数
可以看出指针类型决定了指针+1向后跳几个字节
下面我们用代码研究一下他们的实际意义
把该数组元素全改为1
那么char类型的指针可以吗
这里的数组有十个元素,即有40个字节,int类型指针一次可以修改一个整数元素即四个字节,而char类型一次修改一个字节,所以char类型只把两个半字节改为1
而int*可以把四十个字节全部修改
三.野指针
1.概念
2.成因
①指针未初始化
②指针越界访问
③指针指向的空间释放
解释一下这个程序:
创建一个test函数,返回a(10)的地址,指针p存储a(10)的地址,但是!当程序结束后,a的地址空间还给系统(空间释放),所以当你再次通过指针p(a的地址)找到这个空间时,你访问的这个空间已经不是这个程序的了。
3.如何规避野指针
下面看一个程序
运行后,可以正确的打印10
但是这个程序有很大的问题,细心的人运行程序后会发现,程序没报错,但会有一个警告
我们来讨论一下
程序运行,test函数起作用,临时变量a被赋值为0,但是当a的地址被返回后,此处的空间释放,所以当指针p再次访问这个空间时,没有任何意义,是非法的。
规避野指针的一个很好的方法可以置之为NULL ,在使用时检查其有效性。
可见当将一个指针置为NULL时,再去访问一个空间程序会崩溃
所以在使用时,可以先判断一下有效性再进行使用
四.指针运算
1.指针±整数
也可以倒着输出
2.指针-指针
指针-指针也就是地址-地址
可以看出指针-指针(地址-地址)得到的实际是两个指针之间元素的个数(ps:指针相减要用大的减去小的,否则会是负数)
有一个误区:
可以看出,指针相减必须指向同一块空间,否则会出错。
下面实用一下 使用指针-指针实现strlen求字符串长度
3.指针的关系运算
指针的关系运算也就是比较大小
前置–,所以vp先向前走一步,再解引用赋值为0,然后循环运行
接下来将这个代码进行简化
但是我们应避免第二种写法,因为标准并不代表它可行
来解释一下这个规定
假设现在有一个数组arr,p1是某个元素的地址,p2是最后一个元素后面那个元素的地址,p3是第一个元素前面那个地址。规定即允许p1与p2比较,但不允许p1与p3比较。
五.指针和数组
可以看出数组名表示的是首元素的地址,但并不是所有的数组名都表示首元素地址,有两个特殊情况
下面来讲解一下
可以看到第一行和第二行输出的是首元素地址,第三行输出的是整个数组的地址,但是为什么地址相同呢,该怎么理解呢
可以清晰看出,整个数组的地址也是从第一个元素开始,所以从数值上看是相同的,但是意义却不相同,下面来看一下
所以知道了之后,下面来进行实用
六.二级指针
七.指针数组
指针数组本质是个数组,数组指针本质上是指针
初级指针就介绍到这里,想继续学习可以看进阶指针,但要踏踏实实一步一步向前走,加油!
作者:吕文康
学校:山东第一医科大学
2020年11月6日