函数指针
说明
函数和变量一样,在定义时都需要声明类型,不同的是函数还需要声明传参的类型。变量被保存在内存的某个位置,可以通过指针的方式找到对应的值,函数同样如此,代码段被存储在某个空间,其函数指针就是指向该函数的入口地址。
与变量一样,函数指针能够作为参数进行传递,也能够作为结构体的一部分。
代码示例
#include <stdio.h>
//1.带有函数指针的结构体
typedef struct{
double (*function)(int ,double);
int a;
double b;
}function_ptr;
//2.函数指针做传递参数
double add(int a,double b);//加
double sub(int a,double b);//减
double execl(double function(int ,double),int a,double b);//中介
int main()
{
//1.函数指针做传递参数
double result=execl(add,3,4.22);
double result1=execl(sub,3,4.22);
printf("add=%f\n",result);
printf("sub=%f\n",result1);
//2.函数指针做结构体参数
function_ptr fun[]={
{add,23,32.776},
{sub,32,23.89}
};
for(int i=0;i<(int)sizeof(fun)/(int)sizeof(function_ptr);i++)
{
double temp=fun[i].function(fun[i].a,fun[i].b);
printf("fun%d=%f\n",i+1,temp);
}
return 0;
}
double add(int a,double b)
{
return a+b;
}
double sub(int a,double b)
{
return a-b;
}
double execl(double function(int ,double),int a,double b)
{
return function(a,b);
}
void妙用
空指针(void *)是没有关联数据类型的指针。空指针可以保存任何类型的地址,并且可以将其类型转换为任何类型。
void* 可以用来声明无类型的指针
因此可以表示函数的返回类型,和传参时形参指针类型
经过void*修饰的形参可以传入任意类型的指针
同时函数可以返回任意类型数据的指针
只需要在操作指针对应的空间时,转换下对应的类型即可
代码示例
#include<stdio.h>
#include<stdlib.h>
void add_void(void *result,int a,double b);//参数含有void类型的指针
void* add_void_ptr(int size,int a,double b);//返回值(void*)类型
int main(void)
{
//1.void指针传参
void *result=malloc(sizeof(double));//声明void类型的指针,malloc返回的是void类型的指针
add_void(result,10,1.1111);
printf("add_void=%f\n",*(double*)result);
free(result);
//2.具体类型指针传参
double *result1=(double*)malloc(sizeof (double));
add_void(result1,20,2.2222);
printf("add_void1=%f\n",*result1);
free(result1);
//3.返回值为void*类型函数测试
double *result2=(double*)add_void_ptr(sizeof (double),30,3.3333);
printf("add_void2=%f\n",*result2);
free(result2);
int *result3=(int*)add_void_ptr(sizeof(int),40,4.4444);
printf("add_void3=%d\n",*result3);
free(result3);
printf("%d\n",sizeof (double));
printf("%d\n",sizeof (int));
return 0;
}
void add_void(void *result,int a,double b)
{
double *temp=(double*)result;
*temp=a+b;
}
void* add_void_ptr(int size,int a,double b)
{
if(sizeof (double)==size)
{
double* temp=(double*)malloc(sizeof(size));
*temp=a+b;
return temp;
}
else if(sizeof (int)==size)
{
int* temp=(int*)malloc(sizeof(size));
*temp=a+b;
return temp;
}
return NULL;
}
经过上面的介绍,我们可以使用void*类型来定义一种新的函数指针,这种方式能够有效增加函数的复用性(不过返回值最好不要使用)
代码示例
这个示例不是很好,应该多创建几个操作函数,然后使用一个中介函数,可以执行多种类型的函数,以后再写
#include<stdio.h>
typedef enum{add,sub,multiply,except}Op_Type;
typedef struct{
int a;
double b;
int type;//1:加 2:减 3:乘 4:除
double result;
}Op_Value;
void* Op_function(void* value);//将所有的操作放在同一个函数中
void* excel(void* (*function)(void*),void* value);//类似于线程调用函数(学习专业编写的操作)
int main()
{
Op_Value op[]={
{10,1.111,add,0},
{20,2.222,sub,0},
{30,3.3,multiply,0},
{40,4.4,except,0}
};
for(int i=0;i<(int)sizeof (op)/(int)sizeof (Op_Value);i++)
{
void* function=Op_function;//此处多此一举,纯粹为了展示函数指针的用法
//void* excel_ll=excel;//不能使用,不知道怎么回事
double *temp=(double*)excel(function,&op[i]);//返回值不能直接转化为整型,C语言不能使用不同类型的指针指向函数返回的地址,会出现问题 若非要搞 使用联合变量作为参数传进去,但仍需要明确获得的值是什么类型
printf("op%d=%f\n",i,op[i].result);
printf("op返回值=%f\n",*temp);
printf("op整型=%d\n",(int)*temp);//可以通过强制转换的方式转换为整型
}
return 0;
}
void* Op_function(void* value)
{
Op_Value* temp=(Op_Value*)value;//类型转换
switch (temp->type)
{
case add: temp->result=temp->a+temp->b;break;
case sub: temp->result=temp->a-temp->b;break;
case multiply: temp->result=temp->a*temp->b;break;
case except: temp->result=temp->a/temp->b;break;
default:
break;
};
printf("%f\n",temp->result);
return &temp->result;//void*返回类型函数好像可以不用写返回值
}
void* excel(void* (*function)(void* value),void* value)
{
//前面可以写一些变化,导致后面根据传入的操作执行不同的操作
return function(value);
}