2017-02-20 60 views
1

当数组为空时,ARRAY_SIZE是否返回未定义的行为?因为我们做了一个未知的分区sizeof((X)[0])当数组为空时,ARRAY_SIZE是否返回未定义的行为?

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

#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)); 
} 
+4

这不是C++。对于未指定的数组,空数组初始化器被禁止 – mpiatek

+0

由于'sizeof(k [0])'实际上不访问任何内存,所以这不是UB。它与'sizeof(ka)' – rustyx

回答

3

标准C或C++中不可能有零大小的数组。

在C中,您的代码违反了约束条件(空白初始化程序列表在任何地方都是不允许的)。

在C++中它也是一个错误; {}可能不能用于忽略大小的数组定义。 (C++ 14 [dcl.init.aggr]/4)

如果使用非标准的编译器扩展,则行为将取决于该扩展的详细信息。

+0

完全一样,我用gcc编译,它不会返回错误C既不是警告 – MOHAMED

+2

为什么它被零除错误? 'sizeof((X)[0])'是'sizeof(struct ka)',它不是'0'。 – mch

+1

@MOHAMED gcc默认为GNU扩展模式。对于C,使用编译开关'-std = c11 -pedantic',或者对于C++使用'std = C++ 14 -pedantic'来获得标准行为。 –

1

一般而言,从用于存储器访问的点,这是好的,因为,除非的sizeof操作数是VLA型的,它们是不评价。因此,在这种情况下,x[0]不是无效的内存访问。

引用C11,章§6.5.3.4,重点煤矿

sizeof操作者产生其操作数的大小(以字节为单位),其可以是 表达或类型的括号的名称。大小由操作数的类型 决定。结果是一个整数。如果操作数的类型是可变长度数组 类型,则评估操作数; 否则,操作数不会被评估为,结果是一个整数常量 。

在广义上,对于像

int arr[5]= {0}; 

阵列写入

sizeof(arr)/sizeof(arr[10]); 

有效arr[10]没有被评估,这只是关于操作数的大小,而不是内容(所以,不需要解引用)。

这就是说,

  • 零长度数组是没有标准的C,它们是gcc extension
  • sizeof得到的结果大小为size_t,所以我们应该使用%zu格式说明符来打印结果。
+0

被评估的内容与它有什么关系 –

+1

@ M.M解引用无效内存? –

+0

哦,我明白了,他担心x [0]可能是超出界限的访问。 –

相关问题