blj28

导航

函数指针详解

函数指针详解

函数指针是C/C++中非常重要的概念,它允许程序在运行时动态地调用不同的函数。

1. 基本概念

函数指针是指向函数的指针变量,它存储的是函数的入口地址。

2. 函数指针的声明

基本语法

返回类型 (*指针变量名)(参数类型列表);

示例

// 声明一个指向函数的指针,该函数无参数,返回int
int (*func_ptr)(void);

// 声明一个指向函数的指针,该函数有两个int参数,返回int
int (*operation)(int, int);

// 声明一个指向函数的指针,该函数有char*参数,返回void
void (*print_func)(char*);

 

3. 函数指针的使用

基本用法示例

c
#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 (*operation)(int, int);
    
    // 指向add函数
    operation = add;
    printf("10 + 5 = %d\n", operation(10, 5));
    
    // 指向subtract函数
    operation = subtract;
    printf("10 - 5 = %d\n", operation(10, 5));
    
    // 指向multiply函数
    operation = multiply;
    printf("10 * 5 = %d\n", operation(10, 5));
    
    return 0;
}

 

4. 函数指针的初始化

多种初始化方式

c
#include <stdio.h>

void hello() {
    printf("Hello!\n");
}

void world() {
    printf("World!\n");
}

int main() {
    // 方式1:先声明后赋值
    void (*func1)(void);
    func1 = hello;
    func1();
    
    // 方式2:声明时初始化
    void (*func2)(void) = world;
    func2();
    
    // 方式3:使用地址运算符(可选)
    void (*func3)(void) = &hello;
    func3();
    
    return 0;
}

 

5. 函数指针作为参数

回调函数示例

c
#include <stdio.h>

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

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

// 不同的回调函数实现
void print_number(int num) {
    printf("Number: %d\n", num);
}

void print_square(int num) {
    printf("Square of %d: %d\n", num, num * num);
}

void print_double(int num) {
    printf("Double of %d: %d\n", num, num * 2);
}

int main() {
    int numbers[] = {1, 2, 3, 4, 5};
    int size = sizeof(numbers) / sizeof(numbers[0]);
    
    printf("原始数字:\n");
    process_numbers(numbers, size, print_number);
    
    printf("\n平方:\n");
    process_numbers(numbers, size, print_square);
    
    printf("\n两倍:\n");
    process_numbers(numbers, size, print_double);
    
    return 0;
}

 

6. 函数指针作为返回值

函数工厂模式

c
#include <stdio.h>

// 几个操作函数
int add(int a, int b) { return a + b; }
int sub(int a, int b) { return a - b; }
int mul(int a, int b) { return a * b; }

// 返回函数指针的函数
int (*get_operation(char op))(int, int) {
    switch (op) {
        case '+': return add;
        case '-': return sub;
        case '*': return mul;
        default: return NULL;
    }
}

int main() {
    int a = 10, b = 5;
    char operators[] = {'+', '-', '*'};
    
    for (int i = 0; i < 3; i++) {
        int (*operation)(int, int) = get_operation(operators[i]);
        if (operation) {
            printf("%d %c %d = %d\n", a, operators[i], b, operation(a, b));
        }
    }
    
    return 0;
}

 

7. 使用typedef简化函数指针

typedef用法

c
#include <stdio.h>

// 使用typedef定义函数指针类型
typedef int (*MathOperation)(int, int);
typedef void (*PrintFunction)(char*);

// 函数实现
int add(int a, int b) { return a + b; }
int multiply(int a, int b) { return a * b; }
void print_upper(char* str) {
    while (*str) {
        putchar(toupper(*str++));
    }
    putchar('\n');
}

int main() {
    // 使用typedef后的声明更简洁
    MathOperation op1 = add;
    MathOperation op2 = multiply;
    PrintFunction printer = print_upper;
    
    printf("加法: %d\n", op1(5, 3));
    printf("乘法: %d\n", op2(5, 3));
    printer("hello world");
    
    return 0;
}

 

8. 函数指针数组

命令表模式

使用简化模式方便查看,通常情况下的使用如下

声明                                          含义
unsigned char *fun(void)                 函数,返回 unsigned char*
unsigned char (*fun)(void)               函数指针,指向返回 unsigned char 的函数
unsigned char (*fun[])(void)             函数指针数组
unsigned char (*const fun[])(void)       常量函数指针数组
// 命令处理器表
void (*commands[])(void) = {
    cmd_help,
    cmd_start,
    cmd_stop,
    cmd_status,
    NULL  // 结束标记
};

// 状态机处理函数表
void (*state_handlers[])(void) = {
    state_idle,
    state_running,
    state_paused,
    state_error
};

 

 

 

#include <stdio.h>

// 命令函数
void cmd_help() { printf("显示帮助信息\n"); }
void cmd_start() { printf("启动服务\n"); }
void cmd_stop() { printf("停止服务\n"); }
void cmd_status() { printf("显示状态\n"); }
void cmd_exit() { printf("退出程序\n"); }

// 使用typedef简化 typedef void (*Command)(); int main() { // 函数指针数组 Command commands[] = {cmd_help, cmd_start, cmd_stop, cmd_status, cmd_exit}; const char* command_names[] = {"help", "start", "stop", "status", "exit"}; int command_count = sizeof(commands) / sizeof(commands[0]); // 模拟命令执行 for (int i = 0; i < command_count; i++) { printf("执行命令 '%s': ", command_names[i]); commands[i](); } return 0; }

 

9. 实际应用场景

场景1:排序算法选择

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

typedef int (*CompareFunc)(const void*, const void*);

// 不同的比较函数
int ascending(const void* a, const void* b) {
    return (*(int*)a - *(int*)b);
}

int descending(const void* a, const void* b) {
    return (*(int*)b - *(int*)a);
}

void sort_array(int arr[], int size, CompareFunc compare) {
    qsort(arr, size, sizeof(int), compare);
}

int main() {
    int numbers[] = {5, 2, 8, 1, 9};
    int size = sizeof(numbers) / sizeof(numbers[0]);
    
    printf("原数组: ");
    for (int i = 0; i < size; i++) printf("%d ", numbers[i]);
    printf("\n");
    
    // 升序排序
    sort_array(numbers, size, ascending);
    printf("升序排序: ");
    for (int i = 0; i < size; i++) printf("%d ", numbers[i]);
    printf("\n");
    
    // 降序排序
    sort_array(numbers, size, descending);
    printf("降序排序: ");
    for (int i = 0; i < size; i++) printf("%d ", numbers[i]);
    printf("\n");
    
    return 0;
}

场景2:状态机实现

c
#include <stdio.h>

typedef void (*StateHandler)();

void state_idle() { printf("空闲状态 - 等待命令\n"); }
void state_processing() { printf("处理状态 - 正在工作\n"); }
void state_error() { printf("错误状态 - 需要处理错误\n"); }

int main() {
    StateHandler current_state = state_idle;
    int input;
    
    while (1) {
        current_state();
        printf("输入状态 (0:空闲, 1:处理, 2:错误, -1:退出): ");
        scanf("%d", &input);
        
        if (input == -1) break;
        
        switch (input) {
            case 0: current_state = state_idle; break;
            case 1: current_state = state_processing; break;
            case 2: current_state = state_error; break;
            default: printf("无效输入\n");
        }
    }
    
    return 0;
}

10. 注意事项

类型安全

c
// 错误的函数指针赋值
void func_void(void) { }
int func_int(int) { return 0; }

// 以下会导致编译错误或未定义行为
// void (*wrong_ptr)(void) = func_int;  // 错误:类型不匹配
// int (*wrong_ptr2)(int) = func_void;  // 错误:类型不匹配

空指针检查

c
#include <stdio.h>

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

int main() {
    int (*func_ptr)(int, int) = NULL;
    
    // 在使用前检查指针是否为空
    if (func_ptr != NULL) {
        func_ptr(1, 2);  // 安全调用
    } else {
        printf("函数指针为空!\n");
    }
    
    // 正确赋值后使用
    func_ptr = add;
    if (func_ptr) {  // 简写的空指针检查
        printf("结果: %d\n", func_ptr(3, 4));
    }
    
    return 0;
}

总结

函数指针是C/C++中强大的特性,主要用于:

  • 回调函数机制

  • 策略模式实现

  • 命令模式

  • 状态机

  • 动态函数选择

  • 插件架构

掌握函数指针可以让你写出更加灵活和可扩展的代码!

posted on 2025-11-05 16:30  bailinjun  阅读(4)  评论(0)    收藏  举报