我认为使用负面索引只是纯粹的运气。但出于好奇,我尝试了这个。我知道你可以声明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();
}
答案 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;
仍然有效,因为此代码语句导致未定义行为 它写入不属于数组的内存区域,从而覆盖已分配内存的边界。幸运的是,它的工作原理是因为其他实体可能没有使用内存。从技术上讲,它仍然是一种未定义的行为。