26、函数指针与指针函数

厨子大约 4 分钟C语言基础程序程序厨

函数指针

函数指针是存储函数地址的变量。

通过函数指针,我们可以在运行时动态地调用相应的函数。在实现回调函数、事件处理等功能时非常有用。

声明与使用

声明一个函数指针需要指定该指针指向的函数类型,包括返回类型和参数列表。

假设我们有一个返回整型并接受两个整型参数的函数,我们可以这样声明一个指向这种函数的指针:

int (*func_ptr)(int, int);

这里的func_ptr是一个指向函数的指针,该函数接受两个int类型的参数并返回一个int

赋值与调用

给函数指针赋值时,直接赋予函数名即可(函数名在大多数上下文中会被编译器解释为函数的地址)。

通过函数指针调用函数时,可以使用简洁的指针名(参数列表)语法。

示例代码:

#include <stdio.h>

// 定义一个普通函数
int add(int a, int b) {
    return a + b;
}

int main() {
    // 声明一个函数指针
    int (*func_ptr)(int, int);

    // 将函数指针指向add函数
    func_ptr = add;

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

    return 0;
}

上面的代码可读性较差,我一般建议使用typedef封装函数指针的类型,提高代码可读性:

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

// 封装后的函数指针类型
typedef int (*FuncPtr)(int, int);

int main() {
    // 声明一个函数指针变量
    FuncPtr fp = add;

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

    return 0;
}

指针函数

指针函数是返回指针的函数,而不是指向函数的指针。意味着函数本身返回一个指针类型的数据,这个指针可以指向任何有效的数据类型(如整型、字符型、结构体等)。

声明与使用

声明一个指针函数时,需要指定函数的返回类型(即指针类型)和参数列表。

假设我们有一个返回int类型指针且不接受参数的函数,可以这样声明:

int* ptr_func();

这里的ptr_func是一个函数,返回一个指向int的指针。

返回值

指针函数返回的是指针类型的数据。使用这些返回值时,需要确保指针指向的数据是有效的,并且在使用完数据后,注意,这里可能需要释放动态分配的内存。

示例:

#include <stdio.h>
#include <stdlib.h>

// 定义一个指针函数,返回一个指向int的指针
int* create_int(int value) {
    // 动态分配内存并返回一个指向该内存的指针
    int* ptr = (int*)malloc(sizeof(int));
    if (ptr != NULL) {
        *ptr = value;
    }
    return ptr;
}

int main() {
    // 调用指针函数
    int* p = create_int(10);

    // 检查指针是否为空
    if (p != NULL) {
        printf("Value: %d\n", *p);

        // 重点,释放动态分配的内存
        free(p);
    } else {
        printf("Memory allocation failed!\n");
    }

    return 0;
}

总结

  • 函数指针:存储函数地址的变量,用于动态调用函数。
  • 指针函数:返回指针的函数。

练习

  1. 编写一个C语言程序,定义一个函数int add(int a, int b),该函数返回两个整数的和。然后定义一个函数指针变量pAdd,将其指向add函数,并通过pAdd调用add函数,计算并打印35的和。
  2. 编写一个C语言程序,定义一个指针函数int* findMax(int arr[], int size),该函数遍历一个整数数组,返回指向数组中最大值的指针。在主函数中定义一个整数数组,调用findMax函数,并通过返回的指针打印数组中的最大值。

进阶

  1. 理解函数指针的使用场景。
  2. 理解模板方法设计模式,尝试将函数指针运用在模板方法设计模式中。