为啥使用十六进制?

Posted

技术标签:

【中文标题】为啥使用十六进制?【英文标题】:Why use hex?为什么使用十六进制? 【发布时间】:2010-09-19 14:42:19 【问题描述】:

嘿!我在http://www.gnu.org/software/m68hc11/examples/primes_8c-source.html查看这段代码

我注意到在某些情况下他们使用十六进制数字,例如第 134 行:

for (j = 1; val && j <= 0x80; j <<= 1, q++)

现在他们为什么要使用 0x80?我对十六进制不太擅长,但我发现了一个在线十六进制到十进制,它给了我 128 的 0x80。

同样在第 134 行之前,在第 114 行他们有这个:

small_n = (n & 0xffff0000) == 0;

十六进制到十进制给了我 4294901760 的十六进制数。 所以在这一行中,他们做了一点 AND 并将结果与​​ 0 进行比较??

为什么不直接使用数字呢? 任何人都可以解释一下,并请给出其他情况的例子。

我也见过大行代码,其中只是十六进制数字,但从未真正理解为什么:(

【问题讨论】:

【参考方案1】:

在您引用的两种情况下,数字的位模式都很重要,而不是实际数字。

例如, 在第一种情况下, 随着循环的进行,j 将是 1,然后是 2、4、8、16、32、64,最后是 128。

二进制,即

0000:00010000:00100000:01000000:10000001:00000010:00000100:00001000:0000

在 C(C23 之前)或 C++(C++14 之前)中没有二进制常量的选项,但在 Hex 中更清晰一些: 0x010x020x040x080x100x200x400x80

在第二个例子中, 目标是删除值的低两个字节。 所以给定 1,234,567,890 的值,我们希望最终得到 1,234,567,168。 十六进制更清晰:以0x4996:02d2 开头,以0x4996:0000 结尾。

【讨论】:

第二个例子的小修正:它删除了一个四字节数字的低两个字节。删除低四个字节就是“small_n = 0;”。 哦!你知道,我在写“4位”和“两个字节”之间争论不休,所以我很自然地将它们混为一谈……【参考方案2】:

它是一个位掩码。十六进制值使查看底层二进制表示变得容易。 n & 0xffff0000 返回 n 的前 16 位。 0xffff0000 表示“二进制中的 16 个 1 和 16 个 0”

0x80 表示“1000000”,因此您从“00000001”开始并继续将该位向左移动“0000010”、“0000100”等,直到“1000000”

【讨论】:

【参考方案3】:

十六进制(或八进制)数字与底层位模式之间存在直接映射,而十进制则不是这种情况。十进制“9”表示位模式的不同,具体取决于它所在的列以及围绕它的数字 - 它与位模式没有直接关系。在十六进制中,“9”始终表示“1001”,无论是哪一列。 9 = '1001',95 = '*1001*0101' 等等。

作为我 8 位时代的遗迹,我发现 hex 是任何二进制文件的便捷简写。小玩意儿是一种垂死的技能。有一次(大约 10 年前)我在大学三年级的网络论文中看到,班上只有 10%(50 人中有 5 人左右)可以计算位掩码。

【讨论】:

【参考方案4】:

0xffff0000 很容易理解,它是 32 位值的 16 倍“1”和 16 倍“0”,而 4294901760 是魔术。

【讨论】:

【参考方案5】:

C 语言家族一直支持八进制和十六进制,但不支持二进制,这让我很抓狂。我一直希望他们能直接支持二进制:

int mask = 0b00001111;

多年/工作前,在从事涉及大量位级数学的项目时,我受够了,并生成了一个头文件,其中包含所有可能的二进制值(最多 8 位)的定义常量:

#define b0        (0x00)
#define b1        (0x01)
#define b00       (0x00)
#define b01       (0x01)
#define b10       (0x02)
#define b11       (0x03)
#define b000      (0x00)
#define b001      (0x01)
...
#define b11111110 (0xFE)
#define b11111111 (0xFF)

它偶尔会使某些位级代码更具可读性。

【讨论】:

回复:“我一直希望他们能直接支持二进制”——一些编译器确实将其作为扩展实现:我在各种 PIC C 编译器中看到过它,通常类似于“0b10110110 " @Andrew Medico 你用 C++14 实现了你所提到的形式。【参考方案6】:

十六进制的最大用途可能是在嵌入式编程中。十六进制数用于屏蔽硬件寄存器中的各个位,或将多个数值拆分为单个 8、16 或 32 位寄存器。

在指定单个位掩码时,很多人一开始是:

#define bit_0 1
#define bit_1 2
#define bit_2 4
#define bit_3 8
#define bit_4 16
etc...

过了一会儿,他们前进到:

#define bit_0 0x01
#define bit_1 0x02
#define bit_2 0x04
#define bit_3 0x08
#define bit_4 0x10
etc...

然后他们学会作弊,并让编译器生成值作为编译时优化的一部分:

#define bit_0 (1<<0)
#define bit_1 (1<<1)
#define bit_2 (1<<2)
#define bit_3 (1<<3)
#define bit_4 (1<<4)
etc...

【讨论】:

【参考方案7】:

有时,十六进制值的可视化表示使代码更具可读性或可理解性。例如,在查看数字的十进制表示时,位掩码或位的使用变得不明显。

这有时与特定值类型必须提供的空间量有关,因此这也可能起作用。

一个典型的例子可能是二进制设置,所以我们不使用十进制来显示某些值,而是使用二进制。

假设一个对象具有一组非排他性的属性,这些属性的值可以是 on 或 off(其中 3 个) - 表示这些属性状态的一种方法是使用 3 位。

有效的表示是十进制的 0 到 7,但这并不那么明显。更明显的是二进制表示:

000, 001, 010, 011, 100, 101, 110, 111

另外,有些人对十六进制非常满意。另请注意,硬编码的幻数就是这样,无论使用哪种编号系统,它都不是那么重要

希望对你有帮助。

【讨论】:

【参考方案8】:

通常使用十六进制数而不是十进制数,这是因为计算机使用位(二进制数),当您使用位时使用十六进制数也更容易理解,因为从十六进制到二进制更容易十进制转二进制。

OxFF = 1111 1111 ( F = 1111 )

但是

255 = 1111 1111 

因为

255 / 2 = 127 (rest 1)
127 / 2 = 63 (rest 1)
63 / 2 = 31 (rest 1)
... etc

你能看到吗?从十六进制传递到二进制要简单得多。

【讨论】:

【参考方案9】:

一个字节有 8 位。十六进制,以 16 为底,很简洁。任何可能的字节值都使用集合 0..9 中的两个字符加上 a、b、c、d、e、f 来表示。

Base 256 会更简洁。每个可能的字节都可以有自己的单个字符,但大多数人类语言不使用 256 个字符,所以 Hex 是赢家。

要了解简洁的重要性,请考虑早在 1970 年代,当您想要检查您的兆字节内存时,它以十六进制打印出来。打印输出将使用数千页大纸。八进制会浪费更多的树。

【讨论】:

【参考方案10】:

十六进制或十六进制数字表示 4 位数据,0 到 15 或十六进制 0 到 F。两个十六进制值代表一个字节。

【讨论】:

【参考方案11】:

更准确地说,十六进制和十进制都是数字。基数(以 10、16 等为底)是一种以更清晰或更方便的方式呈现这些数字的方式。

在讨论“有多少东西”时,我们通常使用小数。当我们查看计算机上的地址或位模式时,通常首选十六进制,因为通常单个字节的含义可能很重要。

十六进制(和八进制)具有它们是 2 的幂的属性,因此它们可以很好地映射位分组。十六进制将 4 位映射到一个十六进制半字节 (0-F),因此一个字节存储在两个半字节 (00-FF) 中。八进制在数字设备 (DEC) 和其他较旧的机器上很流行,但一个八进制数字映射到三位,因此它不能很好地跨越字节边界。

总体而言,基数的选择是一种使您的编程更容易的方法 - 使用与域最匹配的那个。

【讨论】:

【参考方案12】:

查看文件,这是一些非常棒的代码。希望你擅长 C 而不是将它用作教程......

当您直接在位级别或略高于位级别工作时,十六进制很有用。例如,在驱动程序上工作,您可以直接查看来自设备的位并调整结果,以便其他人可以读取连贯的结果。它是一种紧凑且易于阅读的二进制表示。

【讨论】:

该代码没有任何问题。看着那段代码,我找不到更清晰的方法来编写它而不使用 HEX。

以上是关于为啥使用十六进制?的主要内容,如果未能解决你的问题,请参考以下文章

为啥十六进制颜色值中有前导“#FF”?

为啥我的 JSON 发布请求以十六进制值结束?

为啥 Arduino Midi 库将十六进制 F7 读取为 0

为啥十六进制颜色不适用于 SVG 的 utf8 数据 URL [重复]

为啥十六进制数字以#而不是0x为前缀?

计算机内存地址为啥要用16进制数来表示