当数组为空时,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格式说明符来打印结果。