63

嘿!我在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 进行比较?

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

此外,我还看到了大行代码,其中只是十六进制数字,但从未真正理解为什么:(

4

12 回答 12

106

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

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

在二进制中,即

0000:0001, 0000:0010, 0000:0100, 0000:1000, 0001:0000, 0010:0000,0100:00001000:0000.

在 C(C23 之前)或 C++(C++14 之前)中没有二进制常量的选项,但在 Hex 中更清晰一些: 0x01, 0x02, 0x04, 0x08, 0x10, 0x20,0x400x80.

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

于 2008-10-28T15:25:02.860 回答
19

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

0x80表示“1000000”,所以你从“00000001”开始,然后继续向左移动“0000010”、“0000100”等,直到“1000000”

于 2008-10-28T15:25:49.643 回答
18

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

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

于 2008-10-28T15:37:44.330 回答
16

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

于 2008-10-28T15:26:08.490 回答
11

我发现 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)

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

于 2008-10-28T16:51:09.457 回答
7

十六进制的最大用途可能是在嵌入式编程中。十六进制数用于屏蔽硬件寄存器中的各个位,或将多个数值拆分为单个 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...
于 2008-10-28T17:06:34.370 回答
6

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

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

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

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

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

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

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

我希望这会有所帮助。

于 2008-10-28T15:29:35.160 回答
6

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

OxFF = 1111 1111 ( F = 1111 )

255 = 1111 1111 

因为

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

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

于 2008-10-28T15:40:58.037 回答
4

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

于 2008-10-28T15:26:05.150 回答
4

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

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

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

于 2008-10-29T23:52:10.277 回答
3

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

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

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

总的来说,基数的选择是一种让你的编程更容易的方法——使用最匹配域的那个。

于 2008-10-28T18:05:29.010 回答
2

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

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

于 2008-10-28T15:36:56.300 回答