为什么数组大小声明使用“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。