8

这是获取数组大小的宏

#define array_size(array) \
(sizeof( array ) / (sizeof( array[0] ) * (sizeof( array ) != sizeof(void*) || sizeof( array[0] ) <= sizeof(void*)))

我认为通常 (sizeof(array) / (sizeof(array[0])) 足以获得数组的大小。

我猜那个部分

(sizeof( array[0] ) * (sizeof( array ) != sizeof(void*) || sizeof( array[0] ) <= sizeof(void*)) 

是为了避免整件事除以零,任何人都可以帮忙解释一下吗?

提前致谢。

干杯,

4

3 回答 3

12

sizeof array[0]在除数中乘以

(sizeof( array ) != sizeof(void*) || sizeof( array[0] ) <= sizeof(void*))

使除数为零,如果

sizeof array == sizeof(void*)

sizeof array[0] > sizeof(void*)

在这些情况下,在编译过程中会被零除,这会导致编译失败。

这些检查是一种尝试检测作为指针的参数(无论它们是否是数组到指针转换的结果),因为使用该商无法知道指针指向的“数组”有多大。

如果其他指针类型的大小与 不同,它会失败void*,并且它不会检测到指向不大于void*s 的事物的指针。通过使作者陷入虚假的安全感,它可能弊大于利。

于 2013-04-25T13:07:44.290 回答
6

我认为通常 (sizeof(array) / (sizeof(array[0])) 足以获得数组的大小。

虽然这不是你的主要问题,但你提到了它。在 C++ 中确定数组大小的正确方法是使用模板:

template<typename T, size_t size>
constexpr size_t array_size(T(&)[size]){
    return size;
}
于 2013-04-25T13:38:10.010 回答
1

我认为这部分很清楚:sizeof( array ) / sizeof( array[0] )

这部分(sizeof( array ) != sizeof(void*) || sizeof( array[0] ) <= sizeof(void*))是一个逻辑表达式,因此产生真或假。在计算整个表达式时,sizeof( array[0] )与逻辑表达式相乘,编译器将逻辑表达式转换为 0 或 1。所以你最终得到
sizeof( array ) / (sizeof( array[0] ) * 1)or
sizeof( array ) / (sizeof( array[0] ) * 0)

第一种情况是正常和期望的情况。第二种情况会给你一个编译器错误,因为被零除。因此,如果您调用例如,代码将无法编译:

long *p; // assuming a platform with sizeof(long)==sizeof(void*)
array_size(p);

但它不会捕获如下错误:

char *p;
array_size(p);

对于我希望它编译的情况,它将无法编译:

long x[1]; // assuming a platform with sizeof(long)==sizeof(void*)
array_size(x);

顺便说一句,如果您将此函数声明为宏(在 C++ 中,我真的更喜欢模板样式解决方案),您应该array将宏中的所有内容更改为(array).

于 2013-04-25T13:22:17.780 回答