在编译时验证 c/c++ 预处理宏中的参数是否为 ARRAY 类型
有什么方法可以在 c 宏中在编译时验证参数是数组吗?
Is there any way to validate on compile time in a c macro that an argument is an array ?
例如在这两个宏中:
#define CLEAN_ARRAY(arr)
do {
bzero(arr, sizeof(arr));
} while (0)
和
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
我使用 CTC(X)
宏 尝试了一些东西,但找不到任何如果 arr
不是数组,则验证/警告的方法.
I tried something using CTC(X)
macro , but couldn't find any way to validate/warn if arr
isn't an array.
推荐答案
这是一个纯 C 的解决方案,它不会调用未定义的行为:
Here's a solution in pure C which invokes no undefined behavior:
#define IS_INDEXABLE(arg) (sizeof(arg[0]))
#define IS_ARRAY(arg) (IS_INDEXABLE(arg) && (((void *) &arg) == ((void *) arg)))
如果您需要确保该值是一个数组(否则会导致编译时错误),您可以简单地将其用作枚举语句(或静态变量)的初始化程序,如下所示:
If you need to ensure that the value is an array (then cause a compile time error if not), you can simply use it as an initializer to an enum statement (or a static variable), like this:
static int __ ## arg ## _is_array = IS_ARRAY(arg); // works for an array, fails for pointer.
我不完全确定 VLA 会发生什么,但稍微尝试一下应该会很快找到答案.
I'm not entirely sure what will happen with VLA's, but playing around a bit should find that answer out rather fast.
旧答案:
由于这被标记为 C(和 GCC),我将在这里尝试一个解决方案:
Since this is tagged C (and GCC), I will attempt a solution here:
#define IS_ARRAY(arg) __builtin_choose_expr(__builtin_types_compatible_p(typeof(arg[0]) [], typeof(arg)), 1, 0)
另一种解决方案,使用 C11 的 _Generic
特性 &typeof
:
Another solution, using C11's _Generic
feature & typeof
:
#define IS_ARRAY(arg) _Generic((arg),
typeof(arg[0]) *: 0,
typeof(arg[0]) [sizeof(arg) / sizeof(arg[0])]: 1
)
基本上,它所做的只是使用 GCC 的一些奇特功能来确定参数的类型是否与参数元素类型的数组兼容.它将返回 0 或 1,如果您愿意,您可以将 0 替换为会产生编译时错误的内容.
Basically, all it does is use some fancy features of GCC to determine if the type of the argument is compatible with an array of the type of the argument's elements. It will return 0 or 1, and you could replace the 0 with something that creates a compile time error if you wish.
相关文章