一、什么是指针:
数据类型 定义指针变量 整型 内存编号 访问对应内存
为什么使用指针:
1、函数之间共享变量
输入、输出
2、提高传参效率
指针变量4\8字节
3、使用堆内存时
如何使用指针:
定义:类型* 变量名_p;
变量名以p结尾与普通变量以示区分
一个*只能定义一个指针变量
初始化为NULL
类型决定了能够连续访问的字节数
赋值:变量名_p = 有效地址
p = &变量名
p = malloc(字节数)
解引用:*变量名_p;
通过指针变量中存储的整数编号去访问内存
该过程很可能产生段错误,是由于赋值时的内存地址非法导致的
指针需要注意的问题:
空指针:值为NULL的指针叫做空指针
对空指针解引用一定段错误,用于初始化以及函数返回值的错误标志
如何避免空指针带来的段错误:
来历不明的指针使用前先判断
函数的返回值\函数的参数
野指针:指针的值不确定
对野指针解引用的后果:
1、一切正常
2、段错误
3、脏数据
野指针的危害比空指针要大,因为无法分辨是否是野指针
如何不产生野指针:
1、指针一定要初始化
2、不要返回局部变量的地址
3、堆内存释放后,指向堆内存的指针及时置空
指针运算:
指针 + n 前进n个元素宽度
指针 - n 后退n个元素宽度
指针 - 指针 计算出两个指针之间间隔了多少个元素,必须类型相同才能相减
指针与const:
const int* p\ int const *p 保护指针指向的内存不能修改
int* const p 保护指针的指向不能修改
当函数的参数是指针,但是又不想被函数共享修改时,考虑使用const保护
指针数组与数组指针:
指针数组:成员是指针变量的数组
int* arr[10];
数组指针:专门指向数组的指针
int (*p)[10];
指向长度为10,成员为int类型的数组的指针
指针与数组名区别:
数组名就是数组的首地址,它与数组首地址是映射关系,相当于一个特殊的指针,但是它是个常量,不能修改
数组作为函数的参数传递时,蜕变成指针,因此长度丢失
指针是变量,它与存储的地址之间是指向关系,是可以更改的
当一个指针指向数组首地址时,指针可以当做数组名使用,数组名也可以当做指针使用
二、二级指针:
指向指针的指针,存储的是指针变量的地址
定义:int** 变量名_pp;
赋值:变量名_pp = &指针变量;
解引用:*变量名_pp == 指针变量;
**指针变量 == *指针变量 == 数据
注意:
当函数间需要共享普通变量时,传递一级指针
当函数间需要共享指针变量时,传递二级指针
三、函数指针
函数名就是一个地址(整数),代表了该函数在代码段中的位置
函数指针就是专门指向某种函数的指针,它里面存储的是该函数在代码段中的位置(函数名)
例子:
int (*funcp)(const char*, ...) = scanf;
funcp是指向返回值为int,参数为const char*和...这样函数的指针
funcp("%d",&num);
四、万能指针:void*
在C语言中,任意类型的指针可以自动转换为void*,void*类型的指针也可以自动转换