02_函数指针和void的妙用

函数指针

说明

函数和变量一样,在定义时都需要声明类型,不同的是函数还需要声明传参的类型。变量被保存在内存的某个位置,可以通过指针的方式找到对应的值,函数同样如此,代码段被存储在某个空间,其函数指针就是指向该函数的入口地址。

与变量一样,函数指针能够作为参数进行传递,也能够作为结构体的一部分。

代码示例

#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);
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

月光在发光

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值