八进制/十六进制表示法的起源是什么?

22

一直以来,我从未想过问这个问题;我知道这源自于C++,但背后的理由是什么呢:

  • 按照正常方式指定十进制数
  • 通过前导0指定八进制数
  • 通过前导0x指定十六进制数

为什么是0?为什么是0x?是否存在自然的32进制进展?


它们在BCPL或B中不存在。 - Joe Koberg
6
它源自C语言,而非C++。由于Stroustrup不想在C和C++之间引入不必要的不兼容性,因此C++只是保留了它。 - David Thornley
2
在1976年的C语言中并没有十六进制常量。http://www.cs.bell-labs.com/who/dmr/cman.ps - Joe Koberg
7个回答

24
C语言是C++和Java的祖先,最初由Dennis Richie在70年代初在PDP-8s上开发。这些机器有一个12位地址空间,因此指针(地址)长为12位,并且最方便的表示方法是四个3位八进制数字(第一个可寻址单词将是0000八进制,最后一个可寻址单词为7777八进制)。
八进制不适合映射到8位字节,因为每个八进制数字表示三个比特,因此在八进制表示法中总会有多余的比特可以表示。全真比特字节(1111 1111)在八进制中为377,但在十六进制中为FF。
对于大多数人来说,十六进制更容易在头脑中转换成二进制,因为二进制数字通常用八个一组表示(因为一个字节的大小为8),而八恰好是两个十六进制数字,但在Dennis时代,十六进制表示法会很笨拙并且误导(暗示能够寻址16位)。程序员需要在使用硬件时(其中每个比特通常表示一个物理线路)和在使用位逻辑时(其中每个比特具有程序员定义的含义)考虑二进制。
我想Dennis添加了0前缀作为日常十进制数字的最简单变化,并且对于那些早期的解析器来说最容易区分。
我相信Hex表示法0x__稍后被添加到C中。编译器解析树要区分1-9(十进制常量的第一位数字)、0(八进制常量的第一[无关紧要]位数字)和0x(指示随后的数字是十六进制常量)之间的区别比仅使用前导0作为指示器更为复杂,从而切换从解析后续数字为八进制而不是十进制。
为什么Dennis会这样设计呢?现代程序员并不知道早期的计算机经常通过在CPU的前面板上翻转开关或使用打孔卡片或纸带来切换指令来控制,所有这些环境下节省几个步骤或指令都代表着节省了大量的人力劳动。另外,内存有限且昂贵,因此即使节省几个指令也具有很高的价值。
总之: 0表示八进制,因为它可以有效地解析并且八进制在PDP-8s上很用户友好(至少对于地址操作而言)。

0x代表十六进制,可能是因为它是对八进制前缀标准的自然且向后兼容的扩展,并且仍然相对高效地解析。


9

八进制的零前缀和十六进制的0x来自Unix早期。

八进制存在的原因可以追溯到当有6位字节的硬件时,这使得八进制成为了自然选择。每个八进制数字代表3位,因此6位字节是两个八进制数字。同样地,对于8位字节的十六进制也是如此,其中一个十六进制数字表示4位,因此一个字节是两个十六进制数字。将8位字节表示为八进制需要3个八进制数字,其中第一个只能有值0、1、2和3(第一个数字实际上是'四进制',不是八进制)。除非有人开发出一种字节长度为10位的系统,否则没有理由转向基于32的表示方法,因此10位字节可以表示为两个5位的“nybble”。


1
我认为这个问题与语法的起源有关。 - Joe Koberg

5
“新”数字必须以数字开头,才能与现有语法配合使用。
传统做法是将变量名和其他标识符以字母开头(或几个其他符号,例如下划线或美元符号)。因此,“a”、“abc”和“a04”都是名称。数字以数字开头。所以“3”和“3e5”都是数字。
当你向编程语言添加新功能时,你要使它们适应现有的语法、语法和语义,并尝试使现有代码继续工作。因此,你不想改变语法,使“x34”成为十六进制数或“o34”成为八进制数。
那么,如何将八进制数字适应到这个语法中呢?有人意识到,除了“0”之外,没有必要以“0”开头的数字。没有人需要写“0123”表示123。因此,我们使用前导零来表示八进制数字。
那么,十六进制数字呢?你可以使用后缀,使“34x”表示3416。然而,然后解析器必须读取整个数字,才能知道如何解释数字(除非遇到“a”到“f”的数字,这当然表示十六进制)。对于解析器来说,知道数字是十六进制的早期更“容易”。但你仍然必须以数字开头,而零的技巧已经被使用,所以我们需要其他东西。选择了“x”,现在我们有“0x”表示十六进制。
(以上是基于我对解析和语言发展的一些普遍历史理解,而不是基于编译器开发人员或语言委员会做出的具体决策的知识。)

4

我不确定...

0表示八进制

0x表示十六进制,因为我们已经使用了0来表示八进制,在十六进制中有个x,所以加上它

至于自然进展,最好参考最新的编程语言,这些语言可以附加下标,例如

123_27(将“_”解释为下标)

等等

马克


1
同样。这正是 C 语言的其余部分“设计”的方式。 - T.E.D.
20
x 的发音类似于 "'ex",这是18世纪伦敦佬用来表示 "十六进制数字字面量"的俚语。 - detly
15
哇,我本来想将这个标记为-1,但后来看到@detly的评论,意识到生活是美好的。尽管这个答案以“我不知道”开始,以一个问号和签名结束。 - Dan Rosenstark

2
有没有自然的进制数序列呢?这也是Ada使用16#引入十六进制常量,8#引入八进制,2#引入二进制等形式的原因之一。
但是,在基数方面,我不会过多关注需要为“未来增长”留出空间。这不像RAM或寻址空间,每代都需要增加一个数量级。
事实上,研究表明,八进制和十六进制几乎是人类可读表示法与二进制兼容的理想选择。如果你比八进制更低,它开始需要一个荒谬的数字来表示更大的数字。如果你比十六进制更高,数学表格就会变得非常大。十六进制已经有点太多了,但八进制的问题是它不能均匀地适合一个字节。

1

Base32 有一个标准的编码方式。它与Base64非常相似,但不太方便阅读。我们使用十六进制是因为两个十六进制数字可以表示一个8位字节。而八进制主要用于旧系统中使用12位字节。与将原始寄存器显示为二进制相比,这可以更紧凑地表示数据。

值得注意的是,一些语言使用o###表示八进制,x##或h##表示十六进制,以及许多其他变种。


-1

我认为它实际上来自UNIX/Linux世界,并被C/C++和其他语言采用。但我不知道确切的原因或真正的起源。


2
当C语言出现时,还没有Linux这样的东西。我不确定Unix有多少个版本;可能只有AT&T的一个。 - David Thornley
Unix是用汇编语言编写的,而Linux则是用C语言编写的吗? - J.Hendrix
1
0x绝对是UNIX和C之后的产物。UNIX和C都是在1976年开始发行,并没有使用它。据说它在1978年出现在《C程序设计语言》第一版中。 - Joe Koberg
1
Ritchie的C语言历史:http://cm.bell-labs.com/cm/cs/who/dmr/chist.html - Joe Koberg
2
C语言的创建旨在帮助构建第一个Unix操作系统。因此,在C语言和Unix操作系统早期阶段,“C世界”和“Unix世界”是同一个世界。 - T.E.D.
回到60年代中期的PDP计算机时代,在汇编语言程序中,数字是隐式地以八进制写入的。请参见http://www.textfiles.com/bitsavers/pdf/dec/pdp8/software/DEC-08-CMAB-D_MACRO8.pdf,5-4-2。因此,前导0表示八进制是向普通人使用C编程语言迈出的一步。 - Michel Billaud

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接