在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
相关产品推荐
相关产品推荐

