且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

在编译时,在c / c ++预处理宏中验证参数是ARRAY类型

更新时间:2023-12-01 09:21:46

以下是纯C中的一个解决方案,它不会调用未定义的行为:

 (arg)(sizeof(arg [0]))
#define IS_ARRAY(arg)(IS_INDEXABLE(arg)&&((void *)& arg) ==((void *)arg)))

如果您需要确保该值为数组(如果不是,则会导致编译时错误),您可以简单地将它用作enum语句(或静态变量)的初始化程序,如下所示:

  static int __ ## arg ## _is_array = IS_ARRAY(arg); //为数组工作,失败的指针。 

我不完全确定VLA会发生什么,但是玩一下应该会找到答案




老答案:

因为这个被标记为C(和GCC),我会在这里尝试一个解决方案:

  #define IS_ARRAY(arg)__builtin_choose_expr(__ builtin_types_compatible_p(typeof (arg [0])[],typeof(arg)),1,0)

,使用C11的 _Generic 功能& typeof

  #define IS_ARRAY(arg)_Generic((arg) ,\ 
typeof(arg [0])*:0,\
typeof(arg [0])[sizeof(arg)/ sizeof(arg [0])]:1 \





$ b基本上,它所做的只是使用GCC的一些奇特功能来确定类型的参数与参数元素类型的数组兼容。它会返回0或1,如果你愿意的话,你可以将0替换为会产生编译时错误的东西。

Is there any way to validate on compile time in a c macro that an argument is an array ?

e.g in this two macros:

#define CLEAN_ARRAY(arr) \
    do { \
        bzero(arr, sizeof(arr)); \
    } while (0)

And

#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))

I tried something using CTC(X) macro , but couldn't find any way to validate/warn if arr isn't an array.

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.

I'm not entirely sure what will happen with VLA's, but playing around a bit should find that answer out rather fast.


Old answers:

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)

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\
)

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.