当数组为空时,ARRAY_SIZE是否返回未定义的行为?
当数组为空时,ARRAY_SIZE是否返回未定义的行为? 因为我们做了一个不存在的sizeof((X)[0])
#include #include #include #ifndef ARRAY_SIZE #define ARRAY_SIZE(X) sizeof((X))/sizeof((X)[0]) #endif struct ka { int a; int b; }; int main(void) { struct ka k[] = {}; printf("%d\n", ARRAY_SIZE(k)); }
标准C或C ++中不可能有零大小的数组。
在C中,您的代码是违反约束的(在任何地方都不允许使用空的初始化列表)。
在C ++中,它也是一个错误; {}
不能与省略大小的数组定义一起使用。 (C ++ 14 [dcl.init.aggr] / 4)
如果使用非标准编译器扩展,则行为将取决于该扩展的详细信息。
通常,从内存访问的角度来看,这很好,因为除非sizeof
的操作数是VLA类型,否则不会对它们进行求值。 因此,在这种情况下, x[0]
不是无效的内存访问。
引用C11
,章节§6.5.3.4, 强调我的
sizeof
运算符产生其操作数的大小(以字节为单位),该操作数可以是表达式或类型的带括号的名称。 大小由操作数的类型确定。 结果是整数。 如果操作数的类型是可变长度数组类型,则计算操作数; 否则,不评估操作数 ,结果是整数常量。
从广义上讲,对于像这样的数组
int arr[5]= {0};
写作
sizeof(arr)/sizeof(arr[10]);
也是有效的,因为arr[10]
没有被评估,它只是操作数的大小,而不是内容 (因此,不需要解除引用)。
那说,
- 零长度数组不是标准C,它们是gcc扩展名 。
-
sizeof
产生size_t
的结果,因此我们应该使用%zu
格式说明符来打印结果。