如何在编译期实现基于参数类型的C宏函数分支调用?
编译期解决C语言_Generic分支类型检查报错的方案
你的问题根源在于C11标准中_Generic的特性:所有关联分支的表达式都会被编译器做类型检查,哪怕该分支不会被最终选中。直接在分支中写函数调用会导致不匹配的分支触发参数类型错误。
可行的编译期解决方案
通过函数指针强制转换+多轮_Generic参数选择的方式,让未选中分支的参数不会触发类型检查,同时保证选中分支的调用完全符合函数要求:
struct node1 { int aa; }; struct node2 { int bb; }; extern void bar1(int, struct node1); extern void bar2(struct node2, int); #define mycall(x, op1, op2) \ _Generic((x), \ int: (void(*)(int, struct node1))bar1, \ float: (void(*)(struct node2, int))bar2 \ )( \ _Generic((x), int: op1, float: op2), \ _Generic((x), int: op2, float: op1) \ ) void foo() { int a, b; float f; struct node1 n1; struct node2 n2; mycall(a, b, n1); // 编译期展开为 bar1(b, n1) mycall(f, b, n2); // 编译期展开为 bar2(n2, b) }
原理说明
- 第一层
_Generic根据x的类型返回对应函数的强转函数指针:x为int时,返回适配bar1参数类型的函数指针x为float时,返回适配bar2参数类型的函数指针
- 第二层的两个
_Generic分别根据x的类型选择参数顺序:- 对应
bar1时传递原顺序的op1和op2 - 对应
bar2时传递反转后的op2和op1
- 对应
- 编译器仅会对选中分支的函数指针调用做参数类型检查,未选中分支的表达式仅用于确定类型,不会触发参数匹配错误。
内容的提问来源于stack exchange,提问作者user26966001
相关产品推荐
相关产品推荐

