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

时间:2012-09-27 11:39:25

标签: c arrays indexing semantics

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

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

5 个答案:

答案 0 :(得分:4)

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

不要依赖此类扩展。

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

答案 1 :(得分:0)

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

答案 2 :(得分:0)

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

答案 3 :(得分:0)

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

当您声明一个大小为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一样。数组的名称只是一个指针。

答案 4 :(得分:0)

int array[0]; 

是无效的C代码。它是非标准的符合。您的代码编译干净,因为它使用 compiler specific extension

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

  

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


  

为什么它似乎有效?

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

array[0] = 5; 

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