如何为C语言_Generic宏添加通用指针分支及友好错误提示?
问题解答
一、能否添加分支适配所有剩余指针类型?
不行。C11的_Generic要求精确类型匹配,不同指针类型(比如short*、const struct bla*与const void*)属于不同类型,没法用单个分支覆盖所有未明确列出的指针类型。
要是硬要覆盖所有指针类型,只能逐个枚举所有可能的指针类型分支,但这显然不现实——自定义结构体、联合体的指针根本没法提前列全。
二、如何设置不会误触发的默认分支错误提示?
直接在default分支写static_assert(0, ...)会导致断言无条件触发,因为static_assert是编译期断言,只要编译器解析到就会执行检查,不管是否走到该分支。
可以用以下技巧让断言仅在进入默认分支时生效:
方法一:借助sizeof和匿名结构体
利用_Generic只编译选中分支的特性,把static_assert放在匿名结构体里,只有默认分支被选中时,sizeof操作才会触发结构体编译,进而触发断言:
#define F(x) \ _Generic((x), int: 1, \ char: 2, \ char *: 3, \ const int *: 4, \ default: (void)sizeof(struct { \ static_assert(0, "Unsupported type for argument: " #x); \ }) \ )
通过#x还能把参数表达式字符串化,让错误提示更直观。
方法二:负大小数组触发错误
用负大小数组生成编译错误,同样能达到仅在默认分支触发的效果:
#define _UNSUPPORTED_TYPE(x) (void)sizeof(char[(0) ? 1 : -1]) #define F(x) \ _Generic((x), int: 1, \ char: 2, \ char *: 3, \ const int *: 4, \ default: _UNSUPPORTED_TYPE(x) \ )
这种方式的错误信息不如static_assert友好,但实现简单。
内容的提问来源于stack exchange,提问作者Kevin Meier
相关产品推荐
相关产品推荐

