如何让C语言的_Generic宏支持传入类型名或值作为参数
实现方案
核心思路是利用typeof(C23纳入标准,此前为绝大多数C编译器支持的通用扩展)的特性:typeof本身就支持接受类型名或表达式作为参数,返回对应的类型。我们只需要用typeof(x)统一生成对应类型的复合字面量作为_Generic的选择器,即可完美兼容两种输入场景,同时覆盖算术类型、自定义结构体等所有合法C类型。
示例实现
#include <stdio.h> // 自定义结构体测试用 struct Foo { int val; }; #define F(x) _Generic((typeof(x)){0}, \ int: 1, \ long: 2, \ struct Foo: 3 \ ) int main(void) { struct Foo f = {0}; // 测试类型参数 printf("%d\n", F(int)); // 输出1 printf("%d\n", F(long)); // 输出2 printf("%d\n", F(struct Foo)); // 输出3 // 测试表达式参数 printf("%d\n", F(100)); // 输出1 printf("%d\n", F(100L)); // 输出2 printf("%d\n", F(f)); // 输出3 return 0; }
原理解释
- 当传入参数为类型名时:
typeof(x)直接返回该类型,构造复合字面量(类型){0}完全合法 - 当传入参数为表达式时:
typeof(x)返回表达式的求值类型,同样可以构造合法的复合字面量 - 完全对齐
sizeof的参数适配逻辑,没有原实现中算术类型不支持结构体、复合字面量不支持字面量值的缺陷
如果需要严格兼容纯C11标准(无typeof扩展),目前没有通用的语法技巧可以实现该需求,C标准中没有无需扩展就能同时区分/适配类型名和表达式作为宏参数的机制。
内容的提问来源于stack exchange,提问作者aghast
相关产品推荐
相关产品推荐

