编程语言用法
这种设计方案嵌入在许多具影响力的编程语言中,包括C,Java和Lisp。在这三种语言中,序列类型(C阵列,Java阵列和串列,Lisp串列和向量)以数字零为下标开始索引。特别是在C语言中,阵列与指针运算紧密相关,这使得一个更简单的实现:下标的参考是从阵列起始位置的偏移,因此第一个元素的偏移量就是零。
几乎所有计算机结构,都借由位址和偏移量来表示直接引用内存,因此C语法的设计细节使编译更容易,但代价是一些人工成本。这样的情况下,使用“第零”作为序数并不是严明正确的,而是计算机业界的普遍惯例。其他编程语言如Fortran或COBOL,则有从一开始的阵列索引下标,因为它们意味着高阶编程语言,因此它们必须与通常的序数相对应。一些最近的编程语言如Lua,由于同样原因采用了相同的约定。
零是最低位的无符号整数值,是编程和硬件设计中最基本的类型之一。因此在计算机科学,零经常被当作许多种类的数值递归的基本情况。计算机科学中的证明和其他类型的数学推理通常从零这一数开始。由于这些原因,在计算机科学中,从零而非从一开始计数的方式并不少见,时有用例。
黑客和计算机科学家经常喜欢将出版品的第一章,如果其内容特重于介绍的概念,则称为“第0章”。其中一个经典的例子是在K&R的第一版。近年来在许多纯数学家中也出现这种特征,许多构造被定义为从0开始编号。
如果用阵列表示循环,则模除(modulo)函式即可便利地获得索引,而这会导致零。
数值属性
使用从零开始的编号范围表示为半开区间
[
0
,
n
)
{\displaystyle [0,n)}
,不同于闭合区间
[
1
,
n
]
{\displaystyle [1,n]}
。在算法中经常发生的“空”范围,很难以闭合区间[1,0]来表达。由于这个属性,从零开始的索引潜在地减少了差一和栅栏错误。但另一方面,预先扣除掉重复的计数
n
{\displaystyle n}
,使得从
0
{\displaystyle 0}
到
n
−
1
{\displaystyle n-1}
(包含)的表达较不直觉。有些作者更偏好从
1
{\displaystyle 1}
开始的索引,因为它直接对应了该项目在其它段落中的索引。
零索引惯例的另一个特性是在现代计算机中实作的模运算。通常,模函数将任何模
N
{\displaystyle N}
映射到
0
,
1
,
2
,
…
,
N
−
1
{\displaystyle 0,1,2,\dots ,N-1}
中的一个数字,其中
N
≥
1
{\displaystyle N\geq 1}
。因此在算法(例如计算杂凑表索引)中的许多公式,当序列从零开始索引时,使用模运算可优雅地以代码表示。如上文所提及位址/偏移量的底层逻辑,指针操作也能以零索引更优雅地表示。
为了说明,假设
a
{\displaystyle a}
是阵列中第一个元素的内存地址,
i
{\displaystyle i}
是需求元素的索引。要求所需元素的位址,如果从
1
{\displaystyle 1}
开始计算索引号,则通过以下表式计算:
a
+
s
×
(
i
−
1
)
{\displaystyle a+s\times (i-1)}
,其中
s
{\displaystyle s}
是每个元素的大小。若从0开始计数,则表达式变为:
a
+
s
×
i
{\displaystyle a+s\times i}
,这个简单的算式可在执行时期更有效率地计算。
然而注意,从1开始索引阵列的语法也能从简采用约定:每个“阵列位址”以
a
′
=
a
−
s
{\displaystyle a'=a-s}
来表示;
也就是说,不采用阵列中第一个元素的位址,这种语法使用某个“虚拟”元素的位址,紧接在实际的第一个元素之前。从1开始索引的表式如下:
a
′
+
s
×
i
{\displaystyle a'+s\times i}
因此零索引的执行期效率来自以0暂代第一元素的实际位址,不使用阵列之前的“虚拟”元素位址,此设计策略的优势。可是,直接位于阵列之前的“虚拟”元素位址,或许是与阵列无关的其他项目,能有作用的位址。这种情况可能导致术语上的混乱。
在零索引方案中第1个元素是“下标零”;同理第12个元素是“下标11”。所以从序数到物件数量的转换浮现;n个元素的最高索引会是n−1并且被称为第n元素(表示数量为n,上界索引与计数差一)。反之第一个元素就被称为第零物件(直接以序号指称),以避免混淆。