有没有办法在编译时知道(而不是失败)这是一个数组还是一个整数?
is there a way to know (and not fail) at compile time if this is a array or an integer?
OP:
有没有办法在编译时知道当前对象是数组还是整数?
#include <stdio.h>
#define IS_INDEXABLE(arg) (sizeof(arg[0]))
#define IS_ARRAY(arg) (IS_INDEXABLE(arg) && (((void *) &arg) == ((void *) arg)))
int main(void)
{
int a[5]; // array
int *b = a; // pointer
int n = 10;
int c[n]; // VLA
int d = 4; // integer
printf("%d\n", IS_ARRAY(a)); //works, 1
printf("%d\n", IS_ARRAY(b)); //works, 0 (edit: I want it to be 1)
printf("%d\n", IS_ARRAY(c)); //works, 1
printf("%d\n", IS_ARRAY(d)); //should say 0, but does not compile "error: subscripted value is neither array nor pointer nor vector"
return 0;
}
编辑后的答案:
经过深思熟虑,我得出以下结论:
大多数答案对于问题的第一部分都是正确的,
我的提议也奏效了。
#define IS_ARRAY1(arg) (((void *) &arg) == ((void *) arg))
#define IS_ARRAY2(arg,type) ((sizeof(arg)/sizeof(type) != 1) && (sizeof(arg)/sizeof(type) != sizeof(arg)))
#define IS_ARRAY4(x,type) _Generic((&x), \
type (*)[]: 1, \
default: 0)
第二部分问题会处理
谢谢。
Linux 内核 (gcc, clang) 有
/* Are two types/vars the same type (ignoring qualifiers)? */
#define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
/* &a[0] degrades to a pointer: a different type from an array */
#define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0]))
因为 _Generic
是基于表达式应该与 "association list" 中的所有内容进行类型兼容性比较的要求,你可以这样做:
#define IS_INT_ARRAY(x) _Generic((&x), \
int (*)[]: 1, \
default: 0)
如果参数是 int
数组,那么它将与指向不完整类型(未知大小)的 int
数组的数组指针兼容。
如果参数是一个对象指针,您可以应用&
但它不会产生数组指针。
OP:
有没有办法在编译时知道当前对象是数组还是整数?
#include <stdio.h>
#define IS_INDEXABLE(arg) (sizeof(arg[0]))
#define IS_ARRAY(arg) (IS_INDEXABLE(arg) && (((void *) &arg) == ((void *) arg)))
int main(void)
{
int a[5]; // array
int *b = a; // pointer
int n = 10;
int c[n]; // VLA
int d = 4; // integer
printf("%d\n", IS_ARRAY(a)); //works, 1
printf("%d\n", IS_ARRAY(b)); //works, 0 (edit: I want it to be 1)
printf("%d\n", IS_ARRAY(c)); //works, 1
printf("%d\n", IS_ARRAY(d)); //should say 0, but does not compile "error: subscripted value is neither array nor pointer nor vector"
return 0;
}
编辑后的答案:
经过深思熟虑,我得出以下结论:
大多数答案对于问题的第一部分都是正确的, 我的提议也奏效了。
#define IS_ARRAY1(arg) (((void *) &arg) == ((void *) arg))
#define IS_ARRAY2(arg,type) ((sizeof(arg)/sizeof(type) != 1) && (sizeof(arg)/sizeof(type) != sizeof(arg)))
#define IS_ARRAY4(x,type) _Generic((&x), \
type (*)[]: 1, \
default: 0)
第二部分问题会处理
Linux 内核 (gcc, clang) 有
/* Are two types/vars the same type (ignoring qualifiers)? */
#define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
/* &a[0] degrades to a pointer: a different type from an array */
#define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0]))
因为 _Generic
是基于表达式应该与 "association list" 中的所有内容进行类型兼容性比较的要求,你可以这样做:
#define IS_INT_ARRAY(x) _Generic((&x), \
int (*)[]: 1, \
default: 0)
如果参数是 int
数组,那么它将与指向不完整类型(未知大小)的 int
数组的数组指针兼容。
如果参数是一个对象指针,您可以应用&
但它不会产生数组指针。