如何在C语言中通过宏和函数指针实现类似C++的lambda功能?
问题根因
你当前生成的函数名不符合预期的核心原因是C预处理器的宏拼接操作##会优先执行拼接,再展开参数内的宏,你定义的#define line __LINE__没有经过二次展开就参与拼接,最终直接生成了funcline的固定名称,无法和行号绑定。
修复方案
1. 修正宏展开逻辑
新增两层辅助宏强制预处理器先展开行号再做名称拼接:
// 内层实现拼接,外层先展开所有参数再调用内层 #define CONCAT_IMPL(a, b) a##b #define CONCAT(a, b) CONCAT_IMPL(a, b) // 生成全局唯一的lambda函数名,和定义所在行号绑定 #define LAMBDA_FUNC_NAME CONCAT(lambda_, __LINE__)
2. 调整lambda宏定义
调整参数顺序更符合使用习惯,同时支持直接获取生成的函数指针:
#define lambda(ret_type, ...) \ ret_type LAMBDA_FUNC_NAME(__VA_ARGS__); \ ret_type LAMBDA_FUNC_NAME(__VA_ARGS__)
3. 完整可运行示例
#include <stdio.h> #define CONCAT_IMPL(a, b) a##b #define CONCAT(a, b) CONCAT_IMPL(a, b) #define LAMBDA_FUNC_NAME CONCAT(lambda_, __LINE__) #define lambda(ret_type, ...) \ ret_type LAMBDA_FUNC_NAME(__VA_ARGS__); \ ret_type LAMBDA_FUNC_NAME(__VA_ARGS__) // 定义lambda lambda(void, int a, float b) { printf("Lambda执行输出:a=%d, b=%.2f\n", a, b); } int main(void) { // 方式1:直接调用生成的lambda函数 lambda_17(10, 3.14f); // 方式2:赋值给函数指针,和普通函数用法完全一致 void (*lambda_ptr)(int, float) = lambda_17; lambda_ptr(20, 6.28f); return 0; }
用gcc -E查看预处理器输出可以看到,生成的函数名为lambda_17(和定义所在的第17行匹配),符合预期。
进阶:模拟带捕获的lambda
纯标准C无法直接支持变量捕获,你可以通过结构体绑定函数指针和捕获变量实现类似效果:
// 定义包含捕获变量和函数指针的结构体 typedef struct { int base; // 捕获的外部变量 int (*calc)(int a, int b, void* self); } AddLambda; // 定义带捕获的lambda lambda(int, int a, int b, void* self) { AddLambda* lambda = (AddLambda*)self; return a + b + lambda->base; } int main() { AddLambda add = { .base = 5, // 赋值捕获变量 .calc = lambda_28 }; // 调用带捕获的lambda printf("计算结果:%d\n", add.calc(2, 3, &add)); // 输出10 return 0; }
内容的提问来源于stack exchange,提问作者Andrei Alexandru Dughila
相关产品推荐
相关产品推荐

