C语言学习之函数指针

一、函数指针与指针函数

函数指针与指针函数这是大家经常会遇见的一个问题,很容易混淆,我们可以从字面上来理解二者的含义:

1、指针函数

指针函数本质上是描述它是一个函数,只是函数的返回值类型是指针。

如下面的这个函数get_memory()将返回一个指针,那它就是一个指针函数。

char        *get_memory(int        size);

{

                return        (char     *)malloc(size);

}

2、函数指针

函数指针本质上是描述它是一个指针,只不过这个指针的类型是函数。

那什么是函数指针呢?首先,函数名就是函数的入口地址,既然它是一个地址,那就可以用一个指针来指向它。这样,指向函数的指针就是函数指针 。那么函数指针该如何定义、如何使用呢?

下面我们先用一个例子来简单演示一下:

#include <stdio.h>

int add(int a,int b)
{       
        
        return a+b;
        
}       

int main(int argc,char *argv[])
{       
        
        int     (*ptr)(int,int);        //定义了一个函数指针ptr,接下来详细讲解为什么这样定义
                                        
        ptr = add;      //让指针ptr指向函数add()
                        
        printf("result:%d\n",add(111,555));     //add就是add()函数的入口地址,如果要调用该函数应该这样调用
        printf("result:%d\n",ptr(111,555));     //ptr也是add()函数的入口地址,所以它的调用方式应该跟add()一样
                                                
        return 0;

}

运行结果:

3、函数指针的定义

在main()函数的入口处,我们定义了一个ptr函数指针。那函数指针是如何定义的呢?能不能定义成别的样子呢?接下来让我们一起来看看:

 int        var        //这里我们定义了一个int类型的变量,那么我们该如何定义一个指针

                                        指向它呢?

int         *ptr        //应该这么定义,将var换成*ptr即可

int        *var        //这里我们定义了一个int类型的指针变量,那我们该如何定义一个指针

                                        指向它的?

int        **ptr        //应该这么定义,即把var换成*ptr即可

struct    struct_type        var        //这里我们定义了一个struct   struct_type类型的变量,那我

                                                                们又该如何定义一个指针指向它呢?

struct    struct_type        *ptr        //应该这么定义,即把var换成*ptr即可

int        func(int    a,int    b)        //如果这里是一个函数,那么该如何定义?

int        *ptr (int    a,int    b)         //应该这么定义,即把var换成*ptr即可吗?

/*

        如果只是这样简单地替换,我们再仔细看看上面的代码:该语句是一条声明语句,

        它声明了一个函数ptr()。该函数有一个int *类型的返回值有两个int类型长度参数

        a和b,而并不是我们想要的定义一个函数指针ptr。之所以出现这个问题,这是因为

        前面的*与int结合了,表示它的返回值是int *类型。如果想要说明它是一个指针,那

        应该让*与ptr结合,而不是与int结合。这时加上一个括号即可。

*/

//所以正确定义函数指针的方式应该是这样的,通过(*ptr)改变了这里*的本质

int        (*ptr)(int    a,int     b)

/*

        那又该如何解读这个函数指针的定义呢?

        1.()使得*与ptr结合,说明ptr是一个指针

        2.前面的int说明该指针指向的函数要有一个int类型的返回值

        3.后面的(int    a,int    b)说明该指针指向的函数要有两个int类型的参数

        4.事实上,函数就是对输入的数据进行处理,并返回相应的结果。所以对于函数而言,

                我们也只需要关心它的输入参数和返回值

        5.由此可以看出,对于ptr指针而言,只要返回值为int并且有两个int类型参数的函数

                都可以指向。

*/ 

//经过上面的学习,叫我们看看下面的两个例子

int        *swap(int   *a,int   *b)        //定义一个这样的函数,那它的函数指针该怎么写?

->>>int        *(*ptr) (int   *a,int   *b)

int        *(*ptr)(int,int   *,char  **)        //定义一个这样的函数,那它的函数指针该怎么写?

->>>int        *func(int,int   *,char  **) 

在这里,我们定义函数指针的时候,定义的语句会很长,代码也不容易看懂,此时我们可以使用typedef关键字来定义一种函数指针类型,从而简化代码,如下图所示:

typedef     int        int_t      //这里使用typedef构造了一个新的类型int_t,事实上它就是int类型

typedef      int  *     int_ptr_t        //这里使用typedef构造一个int_ptr_t,事实上它就是int  *类型

int        func(int   a,int   b)   //这里定义了一个函数,那如何定义一种类型指向这个函数呢

typedef     int    (func_ptr_t  *)(int   a,int   b)  //将func替换成(func_ptr_t  *)并在前面

                                                   加上typedef关键字,此时即定义了一个新的函数指针类型

func_ptr_t                ptr = func        //这时,我们用新的类型func_ptr_t定义了一个函数指针

                                                        ptr,并让ptr指向func函数

二、函数指针使用

通过上面的学习,应该对函数指针有了初步的了解,那我们具体看看函数指针的一些用法吧!

1、函数指针的声明

函数指针的声明形式如下:

return_type   (*pointer_name)   (parameter_types); 

  • return_type 是函数的返回类型。
  • pointer_name 是指针变量的名称。
  • parameter_types 是函数的参数类型。

 例如:int (*add)(int, int);

2、函数指针的赋值

可以将函数的地址赋值给函数指针。注意函数名本身就是一个指向函数的指针

​
#include <stdio.h>

int add(int a, int b) {
    return a + b;
}

int main() {
    int (*sum_ptr)(int, int);  // 声明一个函数指针
    sum_ptr = add;             // 将函数的地址赋值给指针

    // 通过函数指针调用函数
    int result = sum_ptr(3, 4);
    
    printf("Result: %d\n", result);  // 输出:Result: 7

    return 0;
}

 3、使用typedef简化函数指针的声明

通过 typedef 可以简化函数指针的声明,提高代码的可读性。

​
#include <stdio.h>

typedef int (*SumFunction)(int, int);

int add(int a, int b) {
    return a + b;
}

int main() {
    SumFunction sum_ptr = add;  // 使用 typedef 声明函数指针

    int result = sum_ptr(3, 4);
    
    printf("Result: %d\n", result);

    return 0;
}

​

4、函数指针作为参数

函数指针可以作为函数的参数,这样可以传递不同的函数给同一个函数进行处理。

​
#include <stdio.h>

int add(int a, int b) {
    return a + b;
}

int subtract(int a, int b) {
    return a - b;
}

int calculate(int (*operation)(int, int), int x, int y) {
    return operation(x, y);
}

int main() {
    printf("Addition result: %d\n", calculate(add, 5, 3));       // 输出:Addition result: 8
    printf("Subtraction result: %d\n", calculate(subtract, 5, 3));  // 输出:Subtraction result: 2

    return 0;
}

​

5、函数指针数组

 可以创建函数指针数组,用于存储不同函数的地址。

​
#include <stdio.h>

int add(int a, int b) {
    return a + b;
}

int subtract(int a, int b) {
    return a - b;
}

int multiply(int a, int b) {
    return a * b;
}

int main() {
    int (*operations[3])(int, int) = {add, subtract, multiply};

    printf("Addition result: %d\n", operations[0](5, 3));       // 输出:Addition result: 8
    printf("Subtraction result: %d\n", operations[1](5, 3));    // 输出:Subtraction result: 2
    printf("Multiplication result: %d\n", operations[2](5, 3));  // 输出:Multiplication result: 15

    return 0;
}

​

三、回调函数

回调函数(Callback Function)指的是将一个函数作为参数传递给另一个函数,并在后者执行过程中调用前者。函数指针和回调函数之间存在密切的关系。在 C 语言中,回调函数通常通过函数指针来实现。

下面是一个简单的示例,演示了回调函数的用法:

​
#include <stdio.h>

// 回调函数的定义,用于处理数组中的每个元素
typedef void (*CallbackFunction)(int);

// 函数,接受一个数组和数组的大小,以及一个回调函数
void processArray(int arr[], int size, CallbackFunction callback) {
    for (int i = 0; i < size; ++i) {
        // 在适当的时候调用回调函数
        callback(arr[i]);
    }
}

// 回调函数的具体实现,用于打印每个元素的平方
void printSquare(int num) {
    printf("%d ", num * num);
}

int main() {
    int numbers[] = {1, 2, 3, 4, 5};
    int size = sizeof(numbers) / sizeof(numbers[0]);

    // 调用 processArray 函数,并传递 printSquare 函数作为回调
    processArray(numbers, size, printSquare);  // 输出:1 4 9 16 25

    return 0;
}

​
  • 25
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

努力学代码的小信

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

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

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

打赏作者

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

抵扣说明:

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

余额充值