函数与指针分析

本文详细介绍了C语言中函数的类型由返回值和参数决定,包括参数顺序的影响,以及如何通过typedef为函数类型重命名。接着讲解了函数指针的概念,它指向函数的入口地址,可以用于实现回调函数机制。最后,通过实例说明了如何声明和理解复杂的函数指针类型,如右左法则的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

函数类型

C语言中的函数有自己特定的类型

函数类型由返回值参数类型参数个数共同决定

参数类型和参数个数隐含了另一个条件:参数顺序

例:int  add(float i, char j) 的类型为int(int, int),其返回值类型是int,有两个参数,第一个参数float,第二个参数char

        int ff(double e, int i);      //ff函数类型为int(double, int)

        int ff(int i, double e);      //gg函数类型为int(int, double)

        因为函数参数顺序不同,所以这两个函数类型不同

C语言中通过typedef为函数类型重命名

typedef  type name(parameter list)

例:    typedef  int f(int, int);  //定义了一个函数类型f,指的是int(int, int)这类型的函数

    typedef void p(int);     //定义了一个函数类型p,指的是void(int)这类型的函数


函数指针

函数指针用于指向一个函数

函数名是执行函数体的入口地址

可通过函数类型定义函数指针:FuncType*pointer;

也可以直接定义:type (*pointer)(parameter list);

.pointer为函数指针变量名

.type为指向函数的返回值类型

.parameter list为指向函数的类型参数列表

例1:

#include <stdio.h>

typedef int(FUNC)(int);   //把一个int(int)函数类型重定义为FUNC

int test(int i)      //test函数类型也为int(int)
{
    return i * i;
}

void f()     //f函数类型为void()
{
    printf("Call f()...\n");
}

int main()
{
    FUNC* pt = test;   //test函数类型与重定义的FUNC一致,函数名test就是test函数的入口地址,pt是FUNC类型的函数指针,该指针指向test函数
    
    void(*pf)() = &f;  //偷懒的方式定义了一个函数指针pf,指向的函数类型为void(),因此可以把f函数的地址赋给pf,使pf指向f函数
    
    pf();     //新式方法函数调用
    (*pf)();  //老式方法函数调用
    
    printf("Function pointer call: %d\n", pt(2));  //pt(2)等价于直接调用test(2)
}
注:对函数名取地址的意义和函数名本身的意义相同,即f和&f意义相同,test和&test意义相同,这一点函数名和数组名不同,主要是历史原因导致,老的编译器按&f的方式,因为这样写起来麻烦,故新的编译器按照直接f的方式,为了兼容老的规则,所以两种方式都支持

回调函数

回调函数是利用函数指针实现的一种调用机制

回调机制原理

.调用者不知道具体事情发生的时候需要调用的具体函数

.被调函数不知道何时被调用,只知道被调用后需要完成的任务

.当具体事情发生时,调用者通过函数指针调用具体函数

回调机制将调用者和被调函数分开,两者互不依赖

例2:

#include <stdio.h>

typedef int(*FUNCTION)(int);  //FUNCTION是指针类型 

int g(int n, FUNCTION f)   //f是一个指向int(int)类型的函数指针,g就是调用者,f就是被调函数
{
    int i = 0;
    int ret = 0;  
    for(i=1; i<=n; i++)
    {
        ret += i*f(i);
    }    
    return ret;
}

int f1(int x)
{
    return x + 1;
}
int f2(int x)
{
    return 2*x - 1;
}
int f3(int x)
{
    return -x;
}

int main()
{
    printf("x * f1(x): %d\n", g(3, f1));  //g(3, f1)这么写叫注册,把f1作为参数注册给g,g就可以知道f1具体是什么,然后g就可以工作了
    printf("x * f2(x): %d\n", g(3, f2));
    printf("x * f3(x): %d\n", g(3, f3));  //当发生这个事件时,调用者g去调用f3函数
}


指针阅读技巧解析

右左法则

1.从最里层的括号中未定义的标示符看起

2.首先往右看,再往左看

3.当遇到圆括号或者方括号时可以确定部分类型,并调转方向

4.重复2,3步骤,知道阅读结束
例3:

    int (*p2)(int*, int (*f)(int*));
    
    int (*p3[5])(int*);
    
    int (*(*p4)[5])(int*);
    
    int (*(*p5)(int*))[5];

    太麻烦,有空再写


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值