为什么数组大小声明使用“1”作为第一个索引?

关于C#/ Java,我注意到的一点似乎是(对我而言)与数组大小声明和数组大小的默认第一索引不一致的问题。

使用数组时,假设您要创建一个大小为3的新整数数组,它将如下所示:

int[] newArray = new int[3] {1, 2, 3};

完全找到并且可读……对吗?

编程语言的标准似乎要求“第一”索引为0

使用该逻辑,如果我有兴趣创建一个大小为3的数组,我应该写这个:

int[] newArray = new int[2] {1, 2, 3};

等一下…… VS正在抛出一个错误,说an array initialize of length 2 is expected

因此循环数组和数组大小声明的第一个索引是不一致的? 前者使用基于0的索引,第二个使用第1个索引。

这不是任何forms或方式的游戏破坏/改变,但我真的很好奇为什么这里存在差异,或者地狱,如果这甚至是一个问题(就像我说的那样,它不会以任何方式破坏游戏,但我很好奇为什么这样做了)。

我现在可以想到为什么会使用基于1的索引的原因:

在for循环中,您将使用< newArray.Length而不是< newArray.Length - 1< newArray.Length

使用List s一段时间然后回到size-needs-be-declared-arrays会让我有些措手不及。

我认为你把索引器的长度混淆了。 您希望在数组中包含三个元素(或变量),表示为

 ...new int[3]... 

并且大括号中的元素是值,而不是索引。 指数仍为0。 Longform看起来像这样:

 int[] newArray = new int[3]; newArray[0] = 1; newArray[1] = 2; newArray[2] = 3; 

因此,您可以看到基于零的索引与int []的值相关的位置。

因为您声明数组将包含它将包含的元素

我不确定这是不一致的。

你有多少次看到要切3块日志? 提示:不是3次。

另请注意,在post标题中,您错误地将数组大小声明称为“索引”。

 int[] newArray = new int[2] {1, 2, 3}; 

在英语中,这将翻译为“我想要一个可容纳2件物品但放入3件物品的容器”。 您将数组的长度 (它可以容纳多少项)与基于C语言的基于0的数组(例如C,C ++,C#,Java,Javascript,Swift)中的索引相混淆。

另外,考虑一下数组索引究竟是什么(至少使用像C这样的低级语言); 它是数组变量基址的内存偏移量。 所以arr[n]转换为“取arr的地址,在内存中提前n * (the size of my type)字节,并给我计算该地址的值。所以当n = 0时,你引用的值是基本内存地址(数组的开头)。

Wim Hollebrandse提供的答案绝对是伟大而正确的,但是想稍微扩展一下,让OP更加理解为什么索引在大多数(但不是全部)语言中以0开头。

正如Wim所说,在声明时,它将在arrays中存储多少元素,这对于人类的理解是非常可口的。 令人困惑的是为什么第一项实际上被称为第0项(即索引0)…原因是在数组中找到被搜索元素所需的简单数学。

数组中的所有元素按顺序存储在连续的块中。 如果数组位于例如地址100并保持整数(每个大小为4个字节的整数),则在查找第一个项时,它将位于数组的开头,即地址100处。将在第一个或100 + 4 = 104地址之后立即存储。 第3项存储在第2项或地址108之后。

因此,要计算第I个元素的位置,如果索引以0开头,则数学很简单:

 I-th-address = address_of_array + I * sizeof(datatype) eg for our example it is 100 + i * 4 

如果索引以1开头,则数学需要更多操作:

 Ith-address - address of array + (I-1) * sizeof(datatype) 

…比基于0的效率更低,更不必要。

您正在将数组的声明与数组元素的请求混合在一起。 声明一个数组时,指定数组的长度 (元素数),这是3,正确。 当您请求一个元素时,您指定索引 ,并且第一个索引是0.但是您不应该混合索引和数组的长度。

在for循环中,你应该取< newArray.Length :如果你的长度为3,那么循环将从0开始并经过索引0,1和2.然后它停止,因为3不是<3。