2011-05-30 90 views
28

今天我偶然定义了一维为0的二维数组,但是我的编译器没有发出抱怨。我发现其中指出,这是合法的,至少在海湾合作委员会的情况如下:大小为0的数组

6.17 Arrays of Length Zero

不过,我对这个用法两个问题:

首先,这被认为是良好的编程实践?如果是这样,那么我们应该什么时候在真实世界中使用它?

其次,我定义的数组是二维的,一维为0。这与一维情况相同吗?例如,

int s[0] 
int s[0][100] 
int s[100][0] 

它们在内存和编译器中都是一样的吗?

编辑:回复Greg:我使用的编译器是gcc 4.4.5。我对这个问题的意图不是依赖于编译器,但是如果有任何编译器具体的怪癖,这将有所帮助:)

在此先感谢!

+0

鉴于您已经在您的问题中引用了编译器,它将有助于提供有关您所关注的特定编译器的信息。 – Greg 2011-05-30 19:28:01

+1

请检查此问题http://stackoverflow.com/questions/295027/array-of-zero-length – vasin 2011-05-30 19:30:21

+0

请注意,对于C++ 11,“std :: array”类型[可能具有0的大小](http: //en.cppreference.com/w/cpp/container/array)(但普通数组必须至少有一个元素)。 – Cameron 2013-08-24 19:02:36

回答

26

在C++中声明一个长度为零的数组是非法的。因此,当您将代码绑定到特定的编译器扩展时,它通常不被认为是一种好的做法。动态大小的数组的许多用法更好地替换为容器类,如std::vector

ISO/IEC 14882:2003 8.3.4/1:

如果常数表达式(5.19)时,它应是一个积分常数的表达及其值应大于零。

但是,您可以使用new[]动态分配零长度的数组。

ISO/IEC 14882:2003 5.3.4/6:

直接新声明符表达应具有与非负值整数或枚举类型(3.9.1) 。

+1

查尔斯无法理解你可以动态分配一个零长度的数组,你能详细说明这一点。 – 2015-01-09 14:46:52

+2

@Krishna_Oza你可以这样做:'int * x = new int [0];'它会返回一个指针,但取消引用它是未定义的,因为没有可能的理由这样做。编译器可以对其进行解引用,包括崩溃程序。 – smead 2016-02-26 05:27:51

4

我在ideone.com

#include <iostream> 

int main() 
{ 
    int a[0]; 
    int b[0][100]; 
    int c[100][0]; 

    std::cout << "sizeof(a) = " << sizeof(a) << std::endl; 
    std::cout << "sizeof(b) = " << sizeof(b) << std::endl; 
    std::cout << "sizeof(c) = " << sizeof(c) << std::endl; 

    return 0; 
} 

运行这个程序它给了所有变量的大小为0

sizeof(a) = 0 
sizeof(b) = 0 
sizeof(c) = 0 
在上面的例子中

所以,没有内存分配abc

+0

在答案中,您可以添加执行的编译器,因为您指定的链接不显示代码。 – 2015-01-09 14:48:45

+0

@Krishna_Oza ideone.com自2015-10-20起使用gcc 5.1,它是少数几个支持空数组的编译器之一(我发现在将大小不同的数组传递给函数时,我发现它非常便于进行泛型测试,包括空虚作为有效的测试用例)。 – 2015-10-20 08:38:16

2

用gcc编译你的例子,它们全部三个都有sizeof 0,所以我会假设它们都被编译器同等对待。

+1

这将是一个编译器错误*,而不是供应商扩展。 C++要求所有的对象必须至少有一个字节的大小,所以它们得到唯一的地址。 – 2011-05-30 19:45:29

+0

@ Ben Voigt:从原始海报提供的链接中可以看出,gcc明确允许长度为零的数组并不是一个错误。 – Kanopus 2011-05-30 19:57:14

+0

这是一个错误。供应商在接受代码时有很大的余地,标准没有为行为定义,但是当他们这样做时,他们仍然需要遵循适用的任何标准规则。该标准要求每个对象都有唯一的地址和严格的正面大小。子对象需要一个不同于不是父对象的每个对象的地址。 – 2011-05-30 20:50:20

2

您的链接解释了一切。当在编译时不知道struct的长度时,它们被用作结构中的最后一个字段。如果您尝试在堆栈或其他声明中使用它们,您最终会覆盖下一个元素。

相关问题