函数指针
函数在内存中也是存储在代码区,在被调用函数时,会通过函数的地址在代码中定位到函数的代码;
函数指针即为保存函数地址的指针;
返回值类型 (*指针变量名)(形参列表)
如: int (*p)(int,int), void(*p)(void); char * (*p)(void);
代码示例:
#include<stdio.h>
char *fun1()
{
return "hello";
}
char *fun2()
{
static char m[]="lucy";
return m;
}
int main()
{
char *(*p)(void); //char* 为返回值类型,p为函数地址
p=fun2;
printf("%s",p());
return 0;
}
函数指针数组
类似于一个指针数组,区别是数组里的指针指向一个函数
结构为:
返回值类型(*数组名[长度])(形参列表)
例如:
int (*p[3])(int ,int)
代码示例:
#include <stdio.h>
int max(int a ,int b ) //函数名即函数的在内存中的首地址
{
if (a>b)
return a;
else
return b;
}
int min (int a,int b)
{
if(a>b)
return b;
else
return a;
}
int avg(int a,int b )
{
return (a+b)/2;
}
int main()
{
int (*p[3])(int, int)={max,min,avg};
//将max,min,avg三个函数的首地址即数组名传入函数指针数组内
int x=3,y=4;
for(int i =0;i<3;i++)
{
int v=(*(p+i))(x,y);
//分别调用每个函数,在实际开发中经常会运用函数指针数组为开发人员留下接口,后续去开发
printf("最大最小及平均值是%d\n",v);
}
return 0;
}
回调函数
属于函数指针的应用:指的是将函数指针作为函数的参数使用;
例如:
#include <stdio.h>
int getfun(int (*fun)(int ,int),int a,int b)
{ //函数的第一个参数为一个函数指针,在调用时第一个参数传入函数名即可
return fun(a,b);
}
int max(int a ,int b )
{
if (a>b)
return a;
else
return b;
}
int avg(int a,int b )
{
return (a+b)/2;
}
int main()
{
int x=3,y=4;
printf("%d",getfun(avg,x,y));
return 0;
}
动态内存申请
静态分配: 预先确认大小,以数组的形式存在于栈区或全局区。
动态分配: 程序运行过程中,通过内存管理函数从堆申请需要的内存大小的空间。一般以指针变量的形
式存在。
malloc函数
如:
int *arr = (int *)malloc(n * sizeof(int)); //malloc一个参数,即为大小
memset(arr, 0, n * sizeof(int)); //三个参数,地址,默认值,地址大小
特点;
成功时返回首地址的地址,失败时返回null;
申请的内存空间的内容不确定,所以成功后需要memset()函数初始化;
calloc函数
如;
int *p = (int *)calloc(10, sizeof(int));//calloc函数两个参数,内存块数量,每个内存块的大小
特点;
成功时返回首地址,失败时返回null
申请的空间初始值为0;
realloc函数
如;
char *q = realloc(p, 4); //首地址为P的内存空间重新调整为4字节,返回新的内存空间首地址为q
特点:
申请的空间比原来大时,
如果原空间的后面没有被使用,则在其后面申请,且p指针的地址不变;
如果原空间的后面被使用,则会另外找一片空间申请,原指针p被自动释放,返回新指针.
free函数
如;
free(ptr);
释放指针ptr指向的内存空间;
内存泄漏
指的是,在对空间内动态申请内存空间却没有释放