可以理解为指向地址!本质就是地址,需要赋值的也是地址。
ps:我们定义了指针之后尽量要及时进行赋值,以免出现野指针,导致程序出错。如果暂时不知道赋值什么,就可以先赋值为空(null)。
例:
fun函数收到了a,b的地址,括号里面的代表解引用,里面的x就是a,*y就是b。所以a,b被重新赋值了。
指针的偏移(按内存偏)
在数组中,里面的变量都是相同类型,地址连续的。如果我们要选中其中一个数据该怎么做。
例:
因为数组是int类型的,所以一个变量占四个字节,地址是连续的。定义了指针p,然后偏移,+是向右,-是向左,最后输出解引用p,也就是数组中第二个变量的值。
其中因为指针的类型是int型,向右偏移也就是移动了3个变量的地方,12个字节,对应数组(int类型)移动十二个字节也就是移动了3位。
咋解释呢!!指针p是double类型,一开始指向的是数组的首位(1),p++,也就是p向右移动了一位,按照字节就是八个字节(因为是double类型的),所以就是向右移动了八个字节,输出的时候把p转成了int类型,移动八个字节后相当于int类型移动了两个变量,所以对应的就是3。 同理可得:
char类型的数据需要偏移四次才能到第二个数据。
指针也是有类型的,定义就是类型*
特殊指针
1.指针函数
定义:是一个函数,但是这个函数的返回值类型是个指针。
上图的fun函数就是指针函数,返回的值是指针。
2.函数指针
定义:是一个指针,这个指针的指向是一个函数。
函数指针的形参列表就是要指向的函数的形参列表。
将函数指针当做形参,就可以在函数里调用别的函数。
如果给函数指针取别名:
其中pF的函数指针当做类型使用了,定义了pf,其功能和直接在形参里面写函数指针的作用是一样的。
3.常量指针&指针常量
常量指针:是一个指针,指向一个常量。
指针常量:是一个常量,存储的是指针。
为什么上图会报错,因为改变了指针常量的指向。
大端存储和小端存储
大端存储:高位存高位
小端存储:高位存低位
数组指针和指针数组
指针数组:是一个数组,存储的是指针。
数组指针:是一个指针,指向的是一个数组(至少是二维数组↑)
有括号的是数组指针,没括号的是指针数组(咋理解呢!指针需要括号和定义,数组不需要括号和定义)
数组指针的应用:
函数fun的功能是输出2列数组的各个元素,方便之处在于可以输出任何想输出的列数为2的数组。
多级指针:
例:(我觉得有点小难,但是勉强能懂)
下面这个是视频里面的:(目前能看明白!)
内存四区
结构体指针(重要!)
需要注意的是:结构体指针的类型和结构体是一样的!!
例:(结构化数组、指针数组)
例:(指针的偏移)
动态内存分配
(为什么要从堆区申请内存?因为堆区的内存大,栈区的内存有时候不够大。)
:从堆区申请内存,自己使用(记得释放),从堆区申请的内存是通过指针进行管理的!
1.申请是通过函数malloc、calloc、realloc
2.释放是用free函数进行
3.在释放内存的时候,free函数中填的指针,必须要指向内存的首地址
1.malloc
还有就是malloc要引用头文件!(#include <stdlib.h>)
例:
但是!一般都不这么定义!
例:
一般都是这么定义的!!
还有一种赋值方法:(逐字节赋值)
2.realloc(重分配)
本来p是25个字节,但是重新分配之后,就有50个字节,不过只赋值了25个字节,所以后面会出现乱码。
如果内存变小的话(比如10),如果输出25个的话,前十个正常,后面是乱码。
3.calloc
还是需要手动释放。