【问题标题】:Why are hexadecimal numbers prefixed with 0x?为什么十六进制数字以 0x 为前缀?
【发布时间】:2011-02-09 20:51:07
【问题描述】:

为什么十六进制数字前缀为0x? 我了解前缀的用法,但我不明白为什么选择0x 的意义。

【问题讨论】:

  • 现在我意识到标题和正文提出了两个完全不同的问题。大多数回复都集中在标题中的问题上。文中问题的答案很简单:“它没有任何意义——它只是一个前缀,告诉编译器整数是用十六进制写的”。
  • 为了迂腐,人们也可以用两种不同的方式来解释标题中的问题:1)“为什么十六进制数字前缀为 0x,而不是任何其他前缀或指示符?” 2)“为什么我们在输入十六进制数字时需要使用前缀?即使没有前缀,编译器肯定会将58A识别为十六进制数字?”对问题的第二种解释的答案是微不足道的。 “123”也是一个十六进制数。
  • 为什么前缀 0x 表示十六进制数,而不是 0h?

标签: c syntax hex


【解决方案1】:

简短的故事:0 告诉解析器它正在处理一个常量(而不是标识符/保留字)。仍然需要指定数字基数:x 是任意选择。

长话短说:在 60 年代,流行的编程数字系统是十进制和 八进制 — 大型机每个字节有 12、24 或 36 位,可以很好地除以3 = log2(8)。

BCPL 语言使用语法8 1234 表示八进制数。当 Ken Thompson 从 BCPL 创建 B 时,他使用了 0 前缀。这很棒,因为

  1. 整数常量现在总是由单个标记组成,
  2. 解析器仍然可以立即判断它有一个常量,
  3. 解析器可以立即告诉基数(0 在两个基数中是相同的),
  4. 它在数学上是理智的 (00005 == 05),并且
  5. 不需要珍贵的特殊字符(如#123)。

从 B 创建 C 时,需要十六进制数(PDP-11 有 16 位字),以上所有点仍然有效。由于其他机器仍然需要八进制,因此随意选择了0x00 可能被排除在外)。

C# 是 C 的后代,所以它继承了语法。

【讨论】:

  • 我不认为0x 超过00 是偏好/尴尬。 00 会破坏现有代码。八进制的00108,而十六进制的001016。他们不能使用任何数字作为第二位指示符(89 除外,并且两者都没有与十六进制相关的任何意义),因此必须使用字母。这留下了0h0xH e X idecimal)。从这一点来看,它似乎真的回到了偏好。
  • 使用0 前缀作为八进制数多年来引起了很多问题。尤其是在电话号码以0 开头的英国等国家/地区。 Javascript 和许多其他语言会将这些解析为八进制,在存储之前修改数字。为了增加乐趣,如果数字包含89,一种流行的数据库产品会静默切换回十进制解析。
  • 12、24 和 36 也可以被 4 整除,那么他们为什么不考虑使用十六进制呢?
  • @LưuVĩnhPhúc 可能是因为十六进制不是很相关。当时的大多数硬件、软件和文档都更适合八进制。 BCPL 最初是在36 bit IBM 7094 上实现的,指令格式分为两个 3 位部分和两个 15 位部分; 6位字符;和八进制的文档。 B 的早期实现是在 PDP-7(18 位)和 Honeywell GE-945(36 位,但具有 18 位寻址,并支持 6 位和 9 位字节)上实现的。 16位的PDP-11是在B之后出现的,所以对B的设计影响不大。
【解决方案2】:

注意:我不知道正确答案,但以下只是我个人的猜测!

正如前面提到的,数字前的 0 表示它是八进制:

04524 // octal, leading 0

假设需要提出一个系统来表示十六进制数字,并注意我们在 C 风格的环境中工作。像汇编一样以 h 结尾怎么样?不幸的是,你不能 - 它允许你制作有效标识符的标记(例如,你可以将变量命名为相同的东西),这会产生一些令人讨厌的歧义。

8000h // hex
FF00h // oops - valid identifier!  Hex or a variable or type named FF00h?

出于同样的原因,您不能以角色为首:

xFF00 // also valid identifier

使用散列可能因为与预处理器冲突而被丢弃:

#define ...
#FF00 // invalid preprocessor token?

最终,无论出于何种原因,他们决定在前导 0 之后放置一个 x 来表示十六进制。它是明确的,因为它仍然以数字字符开头,因此不能是有效的标识符,并且可能基于前导 0 的八进制约定。

0xFF00 // definitely not an identifier!

【讨论】:

  • 有趣。我想他们可以使用前导 0 和尾随 h 来表示十六进制。尾随的 h 可能会与类型说明符后缀混淆,例如0xFF00l 与 0FF00hl
  • 这个参数意味着使用前导零来表示八进制数早于使用十六进制“0x”前缀。这是真的吗?
  • 它们不是同时被发明的吗?为什么会有一个而没有另一个?
  • AshleysBrain 查看@Řrřola 的回答,了解为什么可能同时存在八进制而不是十六进制。
  • @zdan 他们很久以前就用过了。在 x86 Intel 汇编中,如果十六进制文字以字符开头,则必须始终以 0 为前缀。例如0xFFAB1234 必须写为0FFAB1234h。我记得小时候在 Pascal 中的 inline asm stackoverflow.com/q/11733731/995714
【解决方案3】:

它是一个前缀,表示数字是十六进制而不是其他基数。 C 编程语言使用它来告诉编译器。

示例:

0x6400 转换为 6*16^3 + 4*16^2 + 0*16^1 +0*16^0 = 25600. 当编译器读取0x6400 时,它在0x 术语的帮助下理解该数字是十六进制的。通常我们可以理解为 (6400)16 或 (6400)8 或其他任何..

对于二进制,它将是:

0b00000001

希望我在某些方面有所帮助。

美好的一天!

【讨论】:

  • 自 C++14 起,仅在 C++ 中支持二进制文字,在 C 中完全不支持。
  • 这并不能解释为什么。特别是,为什么你不能把第一个例子写成x6400x 仍可用于推断十六进制。
【解决方案4】:

前面的 0 用于表示以 2、8 或 16 为底的数字。

在我看来,选择 0x 来表示十六进制,因为“x”听起来像十六进制。

只是我的看法,但我认为这是有道理的。

美好的一天!

【讨论】:

  • 感谢您的回答!我知道这是您在 StackOverflow 上的第一篇文章。如果意见与事实分开,答案可能会更有帮助。
  • 这个答案在区分观点和事实方面做得很好。
【解决方案5】:

我不知道 0x 作为前缀来表示十六进制数字背后的历史原因 - 因为它当然可以采用多种形式。这种特殊的前缀样式来自计算机科学的早期。

由于我们习惯于十进制数字,因此通常不需要指出 base/radix。但是,出于编程目的,我们通常需要将基数与二进制 (base-2)、八进制 (base-8)、十进制 (base-10) 和十六进制 (base-16) 区分开来 - 作为最常用的数字基数。

此时,它是用于表示数字基数的约定。我在上面所有的基础上都写了数字 29 和它们的前缀:

  • 0b11101: 二进制
  • 0o35:八进制,用o表示
  • 0d29:十进制,这很不寻常,因为我们假设没有前缀的数字是十进制
  • 0x1D: 十六进制

基本上,我们最常与基数相关联的字母表(例如,b 表示二进制)与0 结合使用以轻松区分数字的基数。

这特别有用,因为较小的数字可能会在所有碱基中混淆地显示相同:0b1、0o1、0d1、0x1。

如果您使用的是富文本编辑器,您也可以使用下标来表示碱基:12、18、110, 116

【讨论】:

  • 为什么不为十六进制选择 0h? 0x 看起来很奇怪。
  • @DawnSong 这只是一个非常流行的约定,现在我们必须接受它。有时这些事情是任意的。你可以尝试推广你的方式,但很难改变这么多人的习惯。我发现八进制在视觉上是最令人困惑的。
猜你喜欢
  • 2020-07-23
  • 2015-11-07
  • 1970-01-01
  • 1970-01-01
  • 2016-03-15
  • 2011-04-30
  • 1970-01-01
  • 1970-01-01
  • 2011-02-26
相关资源
最近更新 更多