零元素数组

8

一个长度为0的数组和未分配的指针一样吗?

int arr[0];int* arr;是一样的吗?

编辑:如果我做了类似下面的事情会怎么样:

int x[0];
int* const arr = x;

我尝试了这段代码并成功编译。据我所知,x和arr应该指向内存中的同一位置。在这种情况下会有什么区别呢?

1
指针可以随时指向新的东西,而数组是静态定义的。 - chrisaycock
3个回答

13

完全不是这样。

对于arr [0]的情况,arr具有明确定义的地址。

在* arr的情况下,arr只是未初始化的。

在您进行编辑后,在其中使用刚刚定义的数组初始化const arr的情况下:变量的内容没有任何区别,但您可以执行的操作有所不同。


@Dasaru 你试过了吗?那个不能编译... - Konrad Rudolph
@Dasaru:通常情况下,您可以...但是由于它是const,您必须手动将arr初始化到给定的内存位置。请参阅https://dev59.com/YHRC5IYBdhLWcg3wROzk - Skippy Fastol
1
在C++中,零长度数组是不合法的,因此该数组将没有明确定义的地址。 - bames53
@bames53:感谢您的澄清。您是否有该信息的来源? - Skippy Fastol
这来自C++标准,[dcl.array] 第8.3.4/1章节。 "如果常量表达式(5.19)存在,则它必须是一个整数常量表达式,并且其值必须大于零"。(可以从这里下载标准。查找文章"n3337")实际上,除了这个引用之外还有更多的内容,但不能全部在这里引用。 - bames53

4
C++中,本地声明的零长度数组是非法的,因此它与未分配的指针不同。

0
一个长度为零的数组指向一个特定的地址,即数组的开头。在数组结束后,您将拥有未定义的数据,在这种情况下,它位于所指向的地址处。
int arr[0];
int* ptr;

// arr is a reliable value;
// *arr is not;
// ptr is not;

这个方法的一个用处:http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Zero-Length.html


据我所知,目前仍然没有共识,即使这种用法是否符合标准是合法的,因为数组越界访问只是未定义行为(UB)(并且确实会导致软件中的错误,这不仅仅是假设)。 - Konrad Rudolph
@KonradRudolph 在 C90 中,这是毫无疑问的:int arr[0] 是非法的,包括在结构体中。如果数组声明为 int arr[1];,并且您使用索引 2 访问它,则行为未定义。在 C99(但不是 C++)中,您可以将结构体的最后一个成员声明为 int arr[]; 以支持此用法(但 int arr[0]; 仍然是错误的)。 - James Kanze
@James 啊,原来是这样。那C++呢?我非常确定越界访问数组从来都不是合法的,我对吗? - Konrad Rudolph
@KonradRudolph 一般来说,对于基本类型、指针和C风格数组,C++的意图是与C相同。 (有一个奇特的架构,C++正式禁止,但C允许,至少在C++03中是这样。这被视为一个缺陷,并且可能已经在C++11中得到修复,尽管我没有验证过。) - James Kanze

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接