我有兴趣编写一个类型验证宏,它只在类型不是 int/short/long 或指针时发出警告。
我遇到的问题是指针可以是任何类型的指针。
#define INT_OR_POINTER_AS_UINTPTR(v) _Generic((v), \
signed long: (uintptr_t)(v), unsigned long: (uintptr_t)(v), \
signed int: (uintptr_t)(v), unsigned int: (uintptr_t)(v), \
signed short: (uintptr_t)(v), unsigned short: (uintptr_t)(v), \
default: (((void)(0 ? (*(v)) : 0), (uintptr_t)(v))))
第一 block 是允许int/short/long
默认
情况是允许任何指针。
(0 ? (*(v)) : 0)
的目的是在 v
不是指针时导致编译器错误,但不影响生成的代码(hance 0 ? ...
)。
这样,来自其他类型(例如 float
或 bool
)的意外隐式转换就不会被忽视。
理想情况下,这会起作用。
int a = 4;
struct Foo *b = NULL;
uintptr_t test_a = INT_OR_POINTER_AS_UINTPTR(a);
uintptr_t test_b = INT_OR_POINTER_AS_UINTPTR(b);
理想情况下,这两种用途都会失败。
float a = 4;
struct Foo b = {0};
uintptr_t test_a = INT_OR_POINTER_AS_UINTPTR(a);
uintptr_t test_b = INT_OR_POINTER_AS_UINTPTR(b);
但是,即使将 int/long/short
作为参数给出,检查指针的代码也会被求值并出现错误:invalid type argument of unary '*' (have 'int')
无需显式枚举可能传递给此 _Generic
的每种指针类型,是否有一种方法可以捕获所有类型的指针,而无需评估其他(非指针)值的表达式?
最佳答案
_Bool
是“标准无符号整数类型”,参见 6.2.5,因此如果您想要对其进行特殊处理,则需要单独进行。
否则,您可以使用一个简单的技巧。整数和指针具有对称差为整数的性质。所以我们在只能接受整数的上下文中使用对称差异,例如数组下标:
#define INT_OR_POINTER_AS_UINTPTR(v) \
((sizeof "Allow only integer and pointer types"[(v)-(v)]), (uintptr_t)(v))
struct
类型的减法会失败,浮点类型会产生浮点差,不能用于指针运算。
要拒绝 _Bool
,您可以使用 _Generic
。
关于c - _Generic 表达式的死分支导致编译器错误 (C11),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27915086/