@Lenciel

为什么数组下标从0开始?

又是个我不知道答案,但又不想用「历史原因」来糊弄的问题。

现成的答案质量都一般

如果用劣质搜索引擎,你会看到一堆下面这样的原因。

但实际上,不是这个原因,也不是这个原因,更不是这个原因

如果搜索手法稍微上档次一点,你可能会看到类似于这篇文章的观点:其实是讲解了 Mike Hoye ——用文章里的话来说——[追根刨地的科学精神]1(http://exple.tive.org/blarg/2013/10/22/citation-needed/)找到的答案。

但是我读了 Mike Hoye 这篇文章,是花了挺大功夫考据,但他的论证过程基本上是:

  1. 最初编程语言中的下标范围要不是从 1 开始,要不就是随意指定的(比如可以是-1:35)
  2. Martin Richards 为了设计一种 IBM 7094 上可以快速编译的专用语言,做了大量优化,其中一个就是让数组下标变成从 0 开始。
  3. 这种叫做 BCPL 的语言,启发了 B 语言,而 B 语言又启发了 C 语言。
  4. C 语言大流行后,这种从 0 开始的数组下标就变成了默认的规矩。

他还举了两个例子说明之前是没有 0 开始但是有 1 开始和任意指定的:

Algol 60 uses one-indexed arrays, and arrays in Fortran are arbitrarily indexed – they’re just a range from X to Y, and X and Y don’t even need to be positive integers.

首先,他弄反了。Algol 60 可以任意指定范围,而 Fortran 才是从 1 开始的。 其次,0 开始的数组也不是 BCPL 的发明:LISP 1.5 这些更早的语言都有从 0 开始的数组。 最后,这个论述方式让我读他有一段话的时候有点懵:

So if your answer started with “because in C…”, you’ve been repeating a good story you heard one time, without ever asking yourself if it’s true.

怎么说呢,你看,基本上他整篇文章浓缩一下,就是在说:

如果有人给你解释,这是因为 C 语言怎样怎样造成的,他就是没有好好研究。我经过了仔细研究才发现,这是因为 C 语言继承了 BCPL 的这种做法,然后流行了,造成的。

那么究竟是怎么回事?

我自己觉得,可能是计算机作为一个学科逐渐形成,里面的标准逐渐固化的一个体现2

对于蒙爷这代人,计算机作为一个学科存在的时间并不长是很反直觉的事情。但实际上,最早从事计算机领域的人,都来自于别的学科:数学、物理、心理学等等。

如果你看数学或者物理的材料,会发现从 0 开始和从 1 开始的索引很常见:比如多项式里大多是从 0 开始,而矩阵预算或者枚举大部分是 1 开始。

因此,在没有标准的阶段,0、1或者是任意指定的范围,都是被广泛使用的。

那么标准为什么逐渐往 0 收拢呢?

BCPL 的作者自己说过:

BCPL was essentially designed as typeless language close to machine code. Just as in machine code registers are typically all the same size and contain values that represent almost anything, such as integers, machine addresses, truth values, characters, etc.

也就是说,Richards 自己解释了,这样的设计更符合计算机的语义,而不是像 Mike 说的那样,仅仅是为了编译效率。

其实在更早的时间,1982 年,Dijkstra 就已经写文章批判了 ALGOL 60(他自己的宝贝)和 Pascal 使用 1 或者任意范围是错误的。

然后,可以看到也是在 C 语言之前, EBDIC 和 ASCII 等都已经是从 0 开始标记的。

再比如同一时期 APL 虽然同时支持 0 或者 1,但 Kenneth Iverson 在他的《A Programming Language》3里面举例时基本上都是 0 开始。

所以,可以看到,随着计算机承担的工作越来越多越来越复杂,大家开始逐渐往最符合机器语义的标准在聚拢:这也使得协作更加简单(你不需要知道引入的库的格式)。

References

  1. 实际上,科学的精神不应该仅仅是竭尽全力找支撑自己论点的论据,还要尽可能站在反方试试自己能不能驳倒自己的论点。 

  2. 但因为不是硬性的标准,所以还是有例外,比如 TLA+ 就仍然是从 1 开始的。 

  3. 《A Programming Language》是本好书。 

寂静无声


她先起来,抱着我的手臂从我怀里抽去。

我顿感身前身后,空空荡荡,无依无靠,只好也起来了。

「我们去找个咖啡厅喝点东西吧。」

这些看起来为了咖啡因的跋涉,或短或长,是我们比亲密相处要得心应手的事儿。

她开车,我玩手机。

Webb 拍的第一批照片发布了,SMACS 0723 八心八箭,船底座星云璀璨而温暖。

车停在一家星巴克门口,我松开安全带。

她没熄火,操作仪表盘,车载音响里张学友行板如歌,说的是她来听我的演唱会。

我手扶在车把上,有点尴尬,不知该继续开门还是窝回座椅。

「我最近一直在想我们的关系。刚刚开车的时候又在想。我还是觉得,自己没有什么可以给你的。刘珩,你呢,你在想什么吗?」

我在想,张学友的歌对于这次谈话来说有点老套。

「我觉得我们接下来要不还是就做朋友吧。我有很多想要去做的事情还没有完成,我很着急。工作、疫情、经济,生活里面各种事情,也让我的状态不好,我没有力气好好对待你。但是我自己就把这个决定做了不太妥当。你应该参与这个决定,而且你可能也需要点儿时间。所以我先告诉你,你想一下。」

Webb 拍的照片,突然模糊。

「那你要和我一起进去,还是在车里等着?」

我气运丹田,挤出个微笑:「就在车里等着。」

她推开车门,消失在咖啡店入口。

好把,这次是这样结束的。

上一次是几个月前,在书店里,来陪我过生日的女朋友突然说,她认为这段关系可能到头了。

「这五年,你应该也早就有这个感觉了,不如还是算了吧。」

她这么说的时候,我心口好像被磨盘压住,无法呼吸。我很想大声质问她我凭什么早就有什么感觉,但发现自己身处书店,不能高声喧哗,只好低声抽泣。

她和书店的服务员一起坐在五米外的楼梯上,静静聆听。事后,她说在一起这么多年,才发现我的哭声羞怯委婉,却又柔韧明亮,比我唱歌好听多了。

就像一棵被小孩儿胡乱提交到 Git 的树,我人生里这样的对话还有更早的版本。

十岁的时候,我妈把我带到幸福饭店。那时候,下馆子的机会不多,我最爱的就是吃幸福饭店。就在我嘴里塞满最喜欢的白果鸡和乌鱼片时,她告诉我,她和我爸过不下去了。

我吞不下食物,也说不出话,最后只能把那些我爱吃的东西都吐到地上,然后开始仰天嚎哭。那声音生硬且凄厉,大概我希望它能像信一样,传至地方,在街道社区,工厂学校,甚至并不遥远的彭州老家,都能带来阵阵回响,让天地都知晓我的委屈。

这委屈是因为没有相亲相爱的父母带来的耻辱,还是因为在饭馆里还没吃好就哭鼻子带来的耻辱,还是什么别的,我也不知道。反正我们再也没有去过幸福饭店,再也没有谈论过这件事情。

他们还是在一起生活,仿佛什么都没有发生,什么都没有改变。

但其实什么都变了。

现在,我独自在星巴克外等着,有点惊讶,这次好像没什么感觉。别说仰天长嚎或者低声抽泣,连胸口发闷都没有。太阳就要落山,空气被加热得很不均匀,让车窗外万事万物波动起舞,仿佛要被融化。我眼中虽有热浪,但车里空调爽利,冷风唤醒精神,世界真切、干脆、清冷。学友唱罢,燕姿登场,一首遇见,说的究竟是遇见还是分开?巴纳姆效应是什么意思来着?

她出来的时候,手里拿着我夏天最爱的冰美式:你看,她还记得我喜欢什么,她可能真的只是没有力气了。

张信哲唱了起来,好像时间回到高中,我刚刚下了自习,站在箭道子灰暗却又喧闹的巷口。

这个时候要是有 Leonard Cohen 的 Paper Thin Hotel 或者 Belle&Sebastian 的…

「我现在就回答你的问题吧。我不知道怎么去接受它,但…」

我停顿了一下。有些东西你并不拥有,丢失时还是痛心疾首。

「好的,我们停下来。好的,我们做朋友。是的,我需要时间,流浪、漫游、无所事事。」

然后她就默默地开动了车。车速不快,四周光影,渐渐隐没云后。天地在夕阳中,像一对依偎着的恋人,无需努力,便已融为一体。

夜晚就要来了。