声明具有0个元素的数组仍然可以存储值

我知道使用负面索引只是纯粹的运气。 但出于好奇,我尝试了这个。 我知道你可以声明array [0]; 就像malloc(0); 是合法的。 但是为什么我可以在array [0]中存储一个值?

#include  #include  int main(void) { int i; int array[0]; array[0] = 5; printf("%d\n",array[0]); getch(); } 

这样一个0大小的数组是标准C中的约束违规,你编译器不应该让你逃脱这个而不给你一个诊断。 如果它没有告诉你什么,那必须是你的编译器供应商添加到其C语言的扩展。

不要依赖这样的扩展。

无论您是否声明大小为0的数组,C都没有对数组或指针访问进行强制绑定检查。 但是,如果在编译时已知超出边界,那么一个好的现代编译器仍应该给出警告。

您正在访问未定义或由其他内容使用的内存空间。 这段代码最终会搞砸了,因为在你使用malloc之前你不知道数组的存在。 您创建了一个大小为零的数组。 C会让你在任何地方写下你想要的任何地方。 禁止操作系统干扰。 “array”是指向数组的指针,它有一些任意值。 编译器不知道在使用它时应该为数组的第零个元素保留该内存空间。

C假设(你可以)你知道你在做什么。 零长度数组仍然具有地址(但该地址可以很容易地与其他大小的地址共享)。 当你索引到那个数组时,你只是修改你正在使用的内存位置,而不用担心还有什么使用你最终得到的地址 – 通过写入,你很容易造成巨大的(并且很难调试)问题。

就像Vikdor在评论中说的那样,你写的是一个不为你保留的记忆位置。 这可能导致严重且难以调试的问题所以我建议你永远不要这样做,但这是它的工作原理:

当你声明一个大小为0 int array[0]int array[0] ,编译器会将名称’array’与一个内存位置相关联。 我们为这个例子说100。 但是因为数组的大小是0,所以没有字节属于数组,因此字节100,101等也可能被分配给其他变量。

当你说array[0] = 5你将数字5写入字节100,101,102和103,因为int是4个字节长。 然后你可以使用从位置100开始读取4个字节的数组[0]来读取该数字。

当从100开始的空间被赋予某个其他变量时会出现一个问题,因为它可能会覆盖数组[0]并且它看起来好像数组[0]已经无缘无故地改变了(这是你将花费大量令人沮丧的时间的地方)调试)

请记住,int array [0]就像int * array。 数组的名称只是一个指针。

 int array[0]; 

是无效的C代码。它是非标准的符合。 您的代码编译干净,因为它使用特定编译器的扩展

参考:
C99标准:6.7.5.2数组声明符
第1段:

除了可选的类型限定符和关键字static之外,[和]可以分隔表达式或* 。 如果它们分隔表达式(指定数组的大小),则表达式应具有整数类型。 如果表达式是常量表达式,则其值应大于零 。 元素类型不应是不完整或函数类型。 可选的类型限定符和关键字static应仅出现在具有数组类型的函数参数的声明中,然后仅出现在最外层的数组类型派生中。


为什么它似乎有效?

假设您的编译器实现允许零长度数组:

 array[0] = 5; 

仍然有效,因为此代码语句导致未定义的行为
它写入不属于数组的内存区域,从而覆盖已分配内存的边界。 幸运的是,它的工作原理是因为某些其他实体可能没有使用内存。 从技术上讲,它仍然是一种未定义的行为。