You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在C语言中如何传递带参数的函数作为回调?

为回调函数传递参数的实现方案

问题描述

现有如下简化C代码,希望为其中的回调函数传递额外参数(当前用于比较的字符'!'是硬编码的),目标实现类似sv_chop_left_while(foo, strlen(foo), is_not_char, '!');的调用方式:

#include <stdbool.h>
#include <string.h>
#include <stdio.h>

char* foo = "hello!!!!";

bool is_not_char(char x)
{
    bool result = false;
    if (x == '!') result = true;
    
    return !result;
}

void sv_chop_left_while(char* input, size_t count, bool (*predicate)(char x))
{
    size_t i = 0;
    while (i < count && predicate(input[i])) {
        printf(">%c< [%d]\n", input[i], i);
        i += 1;
    }
}

int main(void) {
  sv_chop_left_while(foo, strlen(foo), is_not_char);
}

当前程序输出:

>h< [0]
>e< [1]
>l< [2]
>l< [3]
>o< [4]

实现方案

C语言标准函数指针无法直接携带额外参数,以下是两种可行的实现方式:

方法1:结构体封装回调与参数(推荐)

通过结构体打包回调函数和需要传递的参数,避免全局变量的副作用:

#include <stdbool.h>
#include <string.h>
#include <stdio.h>

char* foo = "hello!!!!";

// 定义结构体封装回调函数和目标字符参数
typedef struct {
    bool (*predicate)(char x, char target);
    char target_char;
} PredicateWithArg;

// 调整回调函数,新增目标字符参数
bool is_not_char(char x, char target)
{
    return x != target;
}

// 修改原函数,接收结构体指针
void sv_chop_left_while(char* input, size_t count, PredicateWithArg* pred)
{
    size_t i = 0;
    while (i < count && pred->predicate(input[i], pred->target_char)) {
        printf(">%c< [%d]\n", input[i], i);
        i += 1;
    }
}

int main(void) {
    PredicateWithArg pred = {.predicate = is_not_char, .target_char = '!'};
    sv_chop_left_while(foo, strlen(foo), &pred);
}

方法2:全局变量传递参数(仅临时POC使用)

通过全局变量存储额外参数,实现快速验证,但会降低代码可维护性和线程安全性:

#include <stdbool.h>
#include <string.h>
#include <stdio.h>

char* foo = "hello!!!!";
char global_target; // 全局变量存储目标字符

bool is_not_char(char x)
{
    return x != global_target;
}

// 修改原函数,新增目标字符参数
void sv_chop_left_while(char* input, size_t count, bool (*predicate)(char x), char target)
{
    global_target = target;
    size_t i = 0;
    while (i < count && predicate(input[i])) {
        printf(">%c< [%d]\n", input[i], i);
        i += 1;
    }
}

int main(void) {
  sv_chop_left_while(foo, strlen(foo), is_not_char, '!');
}

验证结果

两种方法运行后,输出均与原代码一致:

>h< [0]
>e< [1]
>l< [2]
>l< [3]
>o< [4]

内容的提问来源于stack exchange,提问作者mbilyanov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 16:24:51