C指针总结
指针
指针的概念
指针是存放地址的变量
取i01地址并放入p01中

打印地址需要使用%p,如下图

指针类型
每一种数据类型都对应一种指针
指针类型有什么用?
分别查询int,char类型地址


Int类型占4个字节

Char类型占1个字节
为了修改时明确修改的字节数,所以使用不同指针类型指定存放的数据类型
Int类型指针变量+1时增加4个字节
Char类型指针变量+1时增加1个字节

野指针(大部分指针问题都来自于此,且有部分难以解决)
野指针就是指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)
野指针成因
指针未初始化

指针越界访问

指针指向的内存被释放(会在动态内存开辟中详细讲解)

如上图,局部变量i01在main01方法结束后已经被释放,但main01传回了i01的地址,所以pi01接收的是一块已经被释放的地址
如何避免野指针
1. 指针创建时初始化(没有确定的值的时候可以赋值NULL空指针)
2. 避免数组越界访问(重要!!系统一般不会报错!!)
3. 指针所指内存释放时(局部变量等)将指针赋值NULL
4. 指针不用时将指针赋值NULL
5. 不访问空指针
指针运算
指针 加减 整数
数组首地址加整数相当于修改访问数组的下标

指针 减 指针
指针之间的加法运算没有意义,减法运算有实用价值
数组地址相减时,不会得到相隔的字节数(相隔元素个数*数据字节数),而是直接得到相隔元素个数

应用:计算字符串长度

指针关系运算
说白了就是比较地址大小( > , < , = )
二级指针

上面定义的i01指向整形0,
指针p01指向i01的地址,
二级指针pp01指向p01的地址,
三级指针ppp01指向pp01的地址,
而最后一行打印的则是0
在这里之所以只讨论二级指针而不说多级指针,是因为只有二级指针有使用价值,再往上的三四级指针并没有什么应用价值
指针数组
定义:

空类型指针
也叫做void 指针,任何类型的指针都可以直接赋值给 void 指针,而无需进行其他相关的强制类型转换。

虽然如此,但这并不意味着可以无需任何强制类型转换就将 void 指针直接赋给其他类型的指针,因为“空类型”可以包容“有类型”,而“有类型”则不能包容“空类型”。正如我们可以说“男人和女人都是人”,但不能说“人是男人”或者“人是女人”一样。

使用场景
指针作参数时
我们想要使用函数修改主函数中的变量时

传参,然后自增,看看这个函数是否可行

调用后发现i01仍然是0,但我们在main01中明明已经自增过了,凭什么主函数不自增?
简单来说,调用函数时,形参i02会自立门户,自己开辟一块内存接收实参i01的变量值0,此时修改i02只是修改这个局部变量的值,i01并不会受影响
我们将i02设为返回值,可以解决这个问题

i01成功自加,但是这种方法,在需要返回多个值或返回数组时,非常不方便
这时就轮到指针出场了,我们将main01的参数换成指针

i01成功自加
使用指针既可以完美实现我们想要的效果,也不需要额外返回值
数组指针作参数时
我们想要使用函数修改主函数中的数组时

数组长度使用sizeof(i01)/sizeof(i01[0])计算
由于数组名本身就是指针,所以这里不需要额外操作
数组本身就是指针,所以数组指针就相当于二重指针,我们来看看数组
常用函数
开辟一块空间malloc关键字
该函数返回一个指针 ,指向已分配大小的内存。如果请求失败,则返回 NULL。
(void *)malloc(size_t size)
参数
void* --返回的指针类型
size -- 内存块的大小,以字节为单位。
实例
返回一个整形指针,开辟n个整形的内存
int *pi01=( int * )malloc( sizeof(int)*n )
C 库函数 – malloc() | 菜鸟教程 (runoob.com)