1.6 函数指针

函数指针单开一章,说明在MCU中,函数指针的用法较为常见,需要完全理解函数指针的各种用法,以便可以更高效的实习自己想要的功能。

函数指针概念

函数指针(Function Pointer)是指向函数的指针,换句话说,函数的地址可以被一个指针变量保存,这个指针变量就是函数指针。

在C语言中,函数也具有地址,因此可以像处理普通变量一样,获取函数的地址,并通过指针调用函数。

主要作用:

  • 动态调用函数:根据不同的条件,调用不同的函数。
  • 回调机制:将函数指针作为参数传递,实现回调函数。
  • 实现多态性:在一定程度上实现类似面向对象的多态特性。

函数指针的声明

return_type (*pointer_name)(parameter_list);
  • return_type:函数的返回类型。
  • pointer_name:函数指针的名称。
  • parameter_list:参数列表,与函数的参数列表相同。

举例:定义一个函数指针,指向返回 int 类型、接受两个 int 参数的函数

int (*func_ptr)(int, int);

函数指针的使用

 

  • 定义函数指针:根据目标函数的类型和参数列表,定义相应的函数指针。
  • 指针赋值:将目标函数的地址赋值给函数指针。
  • 通过函数指针调用函数:使用 (*pointer_name)(arguments) 或 pointer_name(arguments) 语法调用函数。
#include <stdio.h>

// 定义一个函数,求两个整数的和
int add(int a, int b) {
    return a + b;
}

int main() {
    // 1. 定义函数指针
    int (*func_ptr)(int, int);

    // 2. 将函数地址赋值给函数指针
    func_ptr = &add;  // &可以省略,函数名即函数地址

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

    return 0;
}
  • int (*func_ptr)(int, int);:定义了一个函数指针,指向返回 int 类型、接受两个 int 参数的函数。
  • func_ptr = &add;:将函数 add 的地址赋值给函数指针 func_ptr。
    • & 符号可以省略,因为函数名本身就是函数的地址。
  • func_ptr(5, 3);:通过函数指针调用函数,传入参数 5 和 3。

函数指针数组

定义函数指针数组,当需要存储多个函数的地址时,可以使用函数指针数组。

return_type (*array_name[N])(parameter_list);
  • array_name:数组名称。
  • N:数组大小。
#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 divide(int a, int b) {
    if (b != 0)
        return a / b;
    else {
        printf("Division by zero!\n");
        return 0;
    }
}

int main() {
    // 定义一个函数指针数组
    int (*operations[4])(int, int) = {add, subtract, multiply, divide};

    int choice;
    int x = 20, y = 10;
    int result;

    printf("Select operation: 0-Add, 1-Subtract, 2-Multiply, 3-Divide: ");
    scanf("%d", &choice);

    if (choice >= 0 && choice < 4) {
        // 调用选定的函数
        result = operations[choice](x, y);
        printf("Result: %d\n", result);
    } else {
        printf("Invalid choice!\n");
    }

    return 0;
}
  • int (*operations[4])(int, int):定义了一个大小为4的函数指针数组,每个元素都是指向返回 int 类型、接受两个 int 参数的函数。
  • 将 add、subtract、multiply、divide 函数的地址赋值给数组元素。
  • 根据用户输入,选择对应的函数进行计算。

回调函数

回调函数(Callback Function)是一种通过函数指针调用的函数,通常作为参数传递给另一个函数,以便在特定事件或条件下被调用。

回调函数的作用:

  • 实现灵活的代码结构
  • 提高程序的可扩展性和可重用性
#include <stdio.h>

// 比较函数,返回值类似strcmp
int compare_ascending(int a, int b) {
    return a - b;
}

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

// 冒泡排序函数,接受回调函数作为比较依据
void bubble_sort(int arr[], int n, int (*compare)(int, int)) {
    int i, j, temp;
    for (i = 0; i < n - 1; i++) {
        for (j = 0; j < n - 1 - i; j++) {
            if (compare(arr[j], arr[j + 1]) > 0) {
                // 交换元素
                temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
            }
        }
    }
}

int main() {
    int data[] = {5, 3, 8, 6, 2, 7, 4, 1};
    int n = sizeof(data) / sizeof(data[0]);

    // 排序,使用升序比较函数
    bubble_sort(data, n, compare_ascending);

    printf("Ascending order: ");
    for (int i = 0; i < n; i++)
        printf("%d ", data[i]);
    printf("\n");

    // 排序,使用降序比较函数
    bubble_sort(data, n, compare_descending);

    printf("Descending order: ");
    for (int i = 0; i < n; i++)
        printf("%d ", data[i]);
    printf("\n");

    return 0;
}
  • bubble_sort 函数接受一个函数指针 compare 作为参数,用于比较数组元素。
  • compare_ascending 和 compare_descending 是符合要求的回调函数,用于实现不同的排序顺序。
  • 通过传递不同的比较函数,实现了排序方式的灵活切换。
函数指针是C语言中强大而灵活的特性,允许程序在运行时动态地调用函数。

通过函数指针,可以实现回调机制、函数表、多态性等高级功能,提高代码的灵活性和可扩展性。

在使用函数指针时,需要注意类型匹配、可读性和安全性,避免出现错误。