本文通过汇总一些网上搜集到的资料,总结出大部分编程语言中数组下标从0开始的原因

本博客已经迁移至:

本篇博文已经迁移,阅读全文请点击:

背景

我们知道大部分编程语言中的数组都是从0开始编号的,即array[0]是数组的第一个元素。这个和我们平时生活中从1开始编号的习惯相比显得很反人类。那么究竟是什么样的原因让大部分编程语言数组都遵从了这个神奇的习惯呢?本文最初是受stackoverflow上的一个问题的启发,通过搜集和阅读了一些资料在这里做个总结。当然,本文摘录较多的过程结论,如果你想把这篇文章当做快餐享用的话,可以直接跳到文章末尾看结论。

最早的原因

在回答大部分我们无法解释的诡异问题时,我们最常用的辩词通常是历史原因。那么,历史又是出于什么原因,使用了0标号数组呢?Mike Hoye就是本着这么一种追根刨地的科学精神为我们找到了解答。以下是一些他的重要结论的摘录翻译:

据作者的说法,C语言中从0开始标号的做法是沿用了BCPL这门编程语言的做法。而BCPL中如果一个变量是指针的话,那么该指针可以指向一系列连续的相同类型的数值。那么p+0就代表了这一串数值的第一个。在BCPL中数组第5个元素的写法是p!5,而C语言中把写法改成了p[5],也就是现在的数组。具体原文摘录如下:

If a BCPL variable represents a pointer, it points to one or more consecutive words of memory. These words are the same size as BCPL variables. Just as machine code allows address arithmetic so does BCPL, so if p is a pointer p+1 is a pointer to the next word after the one p points to. Naturally p+0 has the same value as p. The monodic indirection operator ! takes a pointer as it’s argument and returns the contents of the word pointed to. If v is a pointer !(v+I) will access the word pointed to by v+I.

至于为什么C语言中为什么使用[]方括号来表示数组下标,这个设计也有一定来历。据C语言作者的说法是方括号是现代键盘上唯一较为容易输入的成对符号(不用shift)不信你对着键盘找找?

为什么这个反人类设计在一段时间内一直没有被改变

根据Mike的说法,BCPL是被设计在IBM硬件环境下编译运行的。在1960后的很长一段时间内,服务器硬件几乎被IBM统治。一个城市内也许至于一台超级计算机,还需要根据时间配额使用。当你当天的配额用完以后,你的程序就被完全清出计算队列。甚至连计算结果都不给你保留,死无全尸。这个时候写一段高效的程序,就显得比什么都重要了。而这时0下标数组又体现了出了它的另一个优势,就是:相较于1下标数组,它的编译效率更高。原文摘录如下:

So: the technical reason we started counting arrays at zero is that in the mid-1960’s, you could shave a few cycles off of a program’s compilation time on an IBM 7094. The social reason is that we had to save every cycle we could, because if the job didn’t finish fast it might not finish at all and you never know when you’re getting bumped off the hardware because the President of IBM just called and fuck your thesis, it’s yacht-racing time.

此外,还有另外一种说法。在C语言中有指针的概念,而指针数组标号实际上是一个偏移量而不是计数作用。例如对于指针p,第N个元素是*(p+N),指针指向数组的第一个元素就是*(p+0),

一些现代语言为什么仍然使用这种做法

上文中提到的为了计较分秒的编译时间而使用0下标数组,在硬件飞速发展的今天显然是不必要的。那么为什么一些新兴语言,如Python依然选择以0作为数组第一个元素呢?难道也是历史原因?对于这个问题,Python的作者Guido van Rossum也有自己的答案。这里大致概括一下作者的用意:从0开始的半开放数组写法在表示子数组(或者子串)的时候格外的便捷。例如:a[0:n]表示了a中前n个元素组成的新数组。如果我们使用1开始的数组写法,那么就要写成a[1:n+1]。这样就显得不是很优雅。那么问题来了,Python数组为什么使用半开放,即[m,n)左闭合右开发的写法呢?这个理解起来就比较简单,读者可以参考http://www.cs.utexas.edu/users/EWD/ewd08xx/EWD831.PDF作为扩展阅读。下面摘录一段Python作者的原话:

Using 0-based indexing, half-open intervals, and suitable defaults (as Python ended up having), they are beautiful: a[:n] and a[i:i+n]; the former is long for a[0:n].

Using 1-based indexing, if you want a[:n] to mean the first n elements, you either have to use closed intervals or you can use a slice notation that uses start and length as the slice parameters. Using half-open intervals just isn't very elegant when combined with 1-based indexing. Using closed intervals, you'd have to write a[i:i+n-1] for the n items starting at i. So perhaps using the slice length would be more elegant with 1-based indexing? Then you could write a[i:n]. And this is in fact what ABC did -- it used a different notation so you could write a@i|n.(See http://homepages.cwi.nl/~steven/abc/qr.html#EXPRESSIONS.)

总结

从0标号的数组传统,沿用了这么长时间的原因主要列举如下:

在计算资源缺乏的过去,0标号的写法可以节省编译时间

现代语言中0标号可以更优雅的表示数组字串

在支持指针的语言中,标号被视作是偏移量,因此从0开始更符合逻辑

参考文献

python的array从0开始吗_为什么数组是从0开始的相关推荐

  1. python数组下标访问起始_为什么数组下标从0开始

    背景 有很多编程语言的数组都是从 0 开始编号,你是否下意识地想过,为什么数组要从 0 开始编号,而不是从 1 开始呢? 从 1 开始不是更符合人类的思维习惯吗?那先看下数组的定义. 数组(Array ...

  2. mate7 android 6 root权限管理,华为Mate7 6.0 root教程_华为Mate7获取6.0系统的root方法

    看到很多机友的华为Ascend Mate7手机系统已经升级到6.0的系统了,可是对于6.0的系统如何进行root呢,很多机友还是比较茫然,所以在这里整理了一下详细的root教程供大家参考了,这个roo ...

  3. 三星 android 5.0 root,三星E330S 5.0 root教程_三星E330S获取5.0系统root的方法

    三星E330S的5.0系统的固件包已经出来了,是官方更新的,已经有机友通过升级的方式升级到5.0的系统了,不过很多人是通过刷机的方式来刷入的,总而之而,不管是哪种方式,只要是手机系统成了5.0的系统之 ...

  4. 三星android 7.0 root,三星G9350 7.0 root教程_三星G9350获取7.0系统的root权限

    咱们的三星G9350手机系统最新版本是安卓7.0的,这一节主要来说说咱们的手机这个手机如何进行root了,这个root操作也是针对7.0的系统进行操作的,因为7.0的系统和之前6.0的系统不同,用6. ...

  5. 获取当天0点时间_什么是股市T+0?该如何做T?

    无论是短线.波段.中线,还是盈利中.套牢中,经常做T远比持股不动好,尤其在大盘震荡.下跌期间,盘中做T是一种非常稳健.高效的套利手段! 只要进入股市,总会有被套的时候. 一般而言,股票被套后有两种应对 ...

  6. sony z2 android 5.0,索尼Xperia Z2 5.0 root教程_索尼Z2获取5.0系统的root

    来说一下咱们的索尼Xperia Z2手机的5.0系统的root,因为现在很多机友的系统是5.0的,可是对于5.0的系统很多机友还不知道如何进行root操作,之前的针对4.4的系统的root方法肯定是用 ...

  7. python查找第k大的数_寻找数组中第K大的数

    给定一个数组A,要求找到数组A中第K大的数字.对于这个问题,解决方案有不少,此处我只给出三种: 方法1: 对数组A进行排序,然后遍历一遍就可以找到第K大的数字.该方法的时间复杂度为O(N*logN) ...

  8. java web 2.0 下载地址_《征服Ajax Web2.0快速入门与项目实践(Java)》[PDF]

    征服Ajax Web2.0快速入门与项目实践(Java) 作者:张桂元 贾燕枫 姜波 基本信息 ·出版社:人民邮电出版社 ·页码:300 页 ·出版日期:2006年 ·ISBN:7115148031 ...

  9. 索尼android 6.0 root,Sony Xperia Z3+ 6.0 root教程_索尼Z3+获取6.0的root权限

    整理了一下咱们的索尼Sony Xperia Z3+手机也相当于咱们的索尼Z4手机的root教程了,有没有需要的呢,在这里说的root教程也是采用卡刷的方式进行root了,之前还有机友在找相关的root ...

最新文章

  1. php 上传 类 代码,php 文件上传类代码
  2. 计算机操作系统32,计算机操作系统实验指导书32138
  3. 中标麒麟mysql导数据_中标麒麟(linux)mysql配置记录
  4. win32 创建进程三种方式简单示例 - 使用CFree
  5. 多选题spss相关分析_SPSS进行典型相关分析结果总结
  6. 返回CompletableFuture:Java 8功能亮点
  7. 计算机的限制而被取消win7,win7系统本次操作由于这台计算机限制而被取消的解决方法...
  8. 我的LAMP实现过程——apache+php
  9. 【Java每日一题】20170110
  10. MUI APP关于页面之间的传值,plusready和自定义事件
  11. rs 华为hcip 课件下载_华为路由与交换hcip最新题库
  12. 中文版-动手学深度学习
  13. LANP+KEEPALIVED集群(一)
  14. 一个老工程师给年轻人的十大忠告【转帖】
  15. IPETRONIK为您提供专业化的数据采集软件IPEmotion进行声学采集与分析
  16. ARVR | 5大AR应用程序开发工具简介
  17. SEO之网站标题间隔符
  18. aws高可用mysql实现_Amazon RDS 的高可用性(多可用区) - Amazon Relational Database Service...
  19. DIL中基本数据类型
  20. EasyNVR网页摄像机直播方案H5前端构建之:区分页面是自跳转还是分享依据

热门文章

  1. cam350 不能打开光绘文件_CAM350使用教程-复制Gerber层
  2. 设计灵感|如何在海报设计中正确使用双色调风格?
  3. 如果你还在寻找完美的海报字体, 你很幸运看这里!
  4. linux和redis笔记,Redis学习笔记一(Redis的详细安装及Linux环境变量配置和启动)...
  5. python软件不用买吗_Python 3.3+中的软件包不需要__init__.py吗
  6. python installer 在 mac 运行_python – 如何在Mac OS X 10.7中的virtualenv中安装PyAudio
  7. python迭代器与生成器_python的迭代器与生成器实例详解
  8. Ubuntu16.04下 shell脚本中C语言形式的for循环用法
  9. OpenShift ocp packages
  10. CentOS7救援模式以及救援模式的网络配置