指针数组:
成员是指针的数组;
int* arr[10];
数组指针:专门用于指向数组的指针
int (*arr)[10];
指针与数组名:
数组名就是数组的首地址,数组名与数组的内存之间是映射关系,相当于一个特殊的指针,是常量,是不能修改的
数组作为函数参数时蜕变为指针,所以长度才丢失,因此需要额外传递长度参数
void func(int* arr)
所以数组名可以解引用,如果指针指向数组,指针可以使用中括号来使用,指针也可以当做数组使用
数组名与内存时映射关系,指针与内存时指向关系
int arr[] <=> int* arr
二级指针:
二级指针就是指向指针的指针,用来存储一级指针变量的地址
定义: 类型** pp;
赋值: pp = &指针变量;
解引用:*pp == 指针变量 == &普通变量
**pp == *指针变量 == 普通变量
注意:当需要共享指针变量时才需要使用二级指针
函数指针:
函数指针就是专门指向函数的指针
函数名就是一个函数在代码段中的内存首地址
调用函数就是跳转到函数所在代码段中的位置执行二进制指令
函数指针中存储的也是函数的首地址,因此对函数指针解引用相当于调用函数
把函数指针当函数一样使用
但是回调函数就需要传递函数指针
定义函数指针:
返回值 (*函数指针名)(类型1,类型2,.....);
赋值:
函数指针名 = 函数名;
调用:
函数指针名(实参);
堆内存管理:
C语言没有控制管理堆内存的语句,只能使用标准C库中的函数来使用
malloc free
int* p = malloc(4);
注意:void*在C++编译器中不能自动转换成其他类型的指针,因此必须要强制类型转换
free
功能:释放一块堆内存
注意:可以释放空指针,不能重复释放,不能释放非法函数
常见的面试题:
1、堆内存与栈内存的区别
是什么,由谁管理,大小,使用情况,安全性,区别
2、堆内存越界的后果
超过33也产生段错误,
破坏了malloc、free的维护信息再次使用malloc、free报错
脏数据
3、什么是内存泄漏,如何定位内存泄漏的
由于业务逻辑出错、粗心大意导致使用完毕后的堆内存没有被释放,当再次使用时又重新申请同样的内存,又没释放,长时间积累导致可用的内存越来越少,系统会越来越慢甚至崩溃,这叫做内存泄漏
1、Windows查看任务管理器,Linux通过ps命令定位泄漏进程
2、使用内存分析工具(mtrace),检查是否有没释放的堆内存
3、封装malloc和free,记录malloc、free使用情况到日志
4、什么是内存碎片?如何减少内存碎片?
已近释放但是也无法使用的内存叫做内存碎片,由于申请和释放的时间、大小不协调导致的
如何尽量减少内存碎片:
1、尽量使用栈内存
2、不要频繁的申请和释放内存
3、尽量申请大块的内存自己管理