首页 > 编程笔记 > C语言笔记(精华版)

C语言函数指针的概念和用法(附带示例)

所谓函数指针,就是指向已定义函数的指针变量。函数指针的本质是指针,而不是函数。函数指针存储了函数在内存中的地址,通过函数指针,我们可以在运行时动态地选择要调用的函数。
 

函数作为一个代码块,编译后也会存储在内存的某个区域(准确来说是内存的代码段);既然在内存中,那它就有地址,就能被指针指向。
 

其实在C语言中,函数名本身就是一个指向函数的指针。当我们在代码中使用函数名时(不带括号),实际上我们使用的是函数的地址。
 

函数指针非常灵活,它允许我们将函数作为参数传递给其他函数,或者将函数作为返回值从函数中返回。

 

函数指针的声明语法可能看起来有些复杂,但掌握了规则后就会发现它其实很直观。函数指针的声明需要指定返回值类型和参数列表,这些信息与它所指向的函数的签名必须完全匹配。

以下是函数指针的一般声明格式:

返回值类型 (*指针名称)(参数类型列表);

让我们通过一个具体的例子来说明函数指针的定义和使用:

#include <stdio.h>

// 定义两个简单的函数
int add(int a, int b) {
    return a + b;
}

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

int main() {
    // 声明一个函数指针
    int (*operation)(int, int);
    
    // 将函数指针指向 add 函数
    operation = add;
    printf("加法结果:%d\n", operation(5, 3));
    
    // 将函数指针指向 subtract 函数
    operation = subtract;
    printf("减法结果:%d\n", operation(5, 3));
    
    return 0;
}

在这个例子中,我们定义了一个名为 operation 的函数指针,它可以指向任何接受两个 int 参数并返回 int 的函数。我们先将它指向 add 函数,然后又将它指向 subtract 函数,通过同一个函数指针调用不同的函数。
 

运行这段代码,我们会得到以下输出:

加法结果:8
减法结果:2


你看,函数指针被定义以后,可以像普通函数一样来使用;而且函数指针指向哪个函数,就调用哪个函数。我们可以通过改变指针的指向,来调用不同的函数。

函数指针的一个重要应用是实现回调函数。回调函数是一种将函数作为参数传递给另一个函数的技术,这使得我们可以在不修改原有函数代码的情况下,通过传入不同的函数来改变其行为。这在很多场景下非常有用,比如排序算法中的比较函数,或者事件驱动编程中的事件处理函数。
 

下面是一个使用函数指针实现回调的例子:

#include <stdio.h>

// 回调函数类型
typedef void (*Callback)(int);

// 接受回调函数作为参数的函数
void processNumbers(int *numbers, int size, Callback callback) {
    for (int i = 0; i < size; i++) {
        callback(numbers[i]);
    }
}

// 两个可能的回调函数
void printNumber(int num) {
    printf("%d ", num);
}

void printSquare(int num) {
    printf("%d ", num * num);
}

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

    printf("原始数字:");
    processNumbers(numbers, size, printNumber);
    
    printf("\n数字的平方:");
    processNumbers(numbers, size, printSquare);
    
    return 0;
}

这个例子中,processNumbers 函数接受一个整数数组、数组大小和一个回调函数作为参数。通过改变传入的回调函数,我们可以灵活地处理数组中的数据。运行这段代码,我们会得到:

原始数字:1 2 3 4 5 
数字的平方:1 4 9 16 25 


函数指针还有一个重要的应用是实现函数表(也称为跳转表)。函数表是一个包含多个函数指针的数组,可以用来根据某个索引或条件快速选择并调用相应的函数。这在实现命令处理、状态机等场景中非常有用。
 

以下是一个使用函数表的简单例子:

#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) { return b != 0 ? a / b : 0; }

int main() {
    int (*operations[])(int, int) = {add, subtract, multiply, divide};
    char *opNames[] = {"加", "减", "乘", "除"};
    int choice, a, b;

    printf("请选择操作(0-加,1-减,2-乘,3-除):");
    scanf("%d", &choice);
    printf("请输入两个数:");
    scanf("%d %d", &a, &b);

    if (choice >= 0 && choice < 4) {
        int result = operations[choice](a, b);
        printf("%d %s %d = %d\n", a, opNames[choice], b, result);
    } else {
        printf("无效的选择\n");
    }

    return 0;
}

在这个例子中,我们定义了一个函数指针数组 operations,其中包含了四个基本算术操作的函数。用户可以通过输入一个数字来选择要执行的操作,程序会使用这个数字作为索引从函数表中选择相应的函数并执行。
 

总之,C语言函数指针的本质是一个指向函数的指针变量。通过函数指针,我们可以实现回调机制、构建插件系统、实现命令模式等高级编程技术。然而,使用函数指针也需要格外小心,因为它们可能导致代码可读性降低,并且如果使用不当,可能引发难以调试的问题。
 

最后,容易和函数指针混淆的另外一个概念是指针函数,如果你希望深入了解指针函数,请转到:

相关文章