【发布时间】:2023-03-12 09:17:01
【问题描述】:
我有兴趣编写一个类型验证宏,它只会在类型不是 int/short/long 或 pointer 时发出警告。
我遇到的问题是指针可以是任何类型的指针。
#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))))
第一块是允许int/short/long
default 的情况是允许任何指针。
(0 ? (*(v)) : 0) 的目的是在v 不是指针时导致编译器错误,否则不会影响生成的代码(请注意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 的每种指针类型,有没有一种方法可以捕获所有类型的指针,而无需评估其他(非指针)值的表达式?
【问题讨论】: