2.1.1 十六进制表示法
2.1.1 十六进制表示法
一个字节由 8 位组成。在二进制表示法中,它的值域是 00000000₂ ~ 11111111₂。如果看成十进制整数,它的值域就是 0₁₀ ~ 255₁₀。两种符号表示法对于描述位模式来说都不是非常方便。二进制表示法太冗长,而十进制表示法与位模式的互相转化很麻烦。替代的方法是,以 16 为基数,或者叫做十六进制(hexadecimal)数,来表示位模式。十六进制(简写为 “hex”)使用数字 0-9 以及字符 A-F 来表示 16 个可能的值。图 2-2 展示了 16 个十六进制数字对应的十进制值和二进制值。用十六进制书写,一个字节的值域为 00₁₆ ~ FF₁₆。

在 C 语言中,以 0x 或 0X 开头的数字常量被认为是十六进制的值。字符 A-F 既可以是大写,也可以是小写。例如,我们可以将数字 FA1D37B₁₆ 写作 0xFA1D37B,或者 0xfa1d37b,甚至是大小写混合,比如 0xFa1D37b。在本书中,我们将使用 C 表示法来表示十六进制值。
编写机器级程序的一个常见任务就是在位模式的十进制、二进制和十六进制表示之间人工转换。二进制和十六进制之间的转换比较简单直接,因为可以一次执行一个十六进制数字的转换。数字的转换可以参考如图 2-2 所示的表。一个简单的窍门是,记住十六进制数字 A、C 和 F 相应的十进制值。而对于把十六进制值 B、D 和 E 转换成十进制值,则可以通过计算它们与前三个值的相对关系来完成。
比如,假设给你一个数字 0x173A4C。可以通过展开每个十六进制数字,将它转换为二进制格式,如下所示:
| 十六进制 | 1 | 7 | 3 | A | 4 | C |
|---|---|---|---|---|---|---|
| 二进制 | 0001 | 0111 | 0011 | 1010 | 0100 | 1100 |
这样就得到了二进制表示 000101110011101001001100。
反过来,如果给定一个二进制数字 1111001010110110110011,可以通过首先把它分为每 4 位一组来转换为十六进制。不过要注意,如果位总数不是 4 的倍数,最左边的一组可以少于 4 位,前面用 0 补足。然后将每个 4 位组转换为相应的十六进制数字:
| 二进制 | 11 | 1100 | 1010 | 1101 | 1011 | 0011 |
|---|---|---|---|---|---|---|
| 十六进制 | 3 | C | A | D | B | 3 |
练习题 2.1
完成下面的数字转换:
A. 将 0x39A7F8 转换为二进制。
B. 将二进制 1100100101111011 转换为十六进制。
C. 将 0xD5E4C 转换为二进制。
D. 将二进制 1001101110011110110101 转换为十六进制。
当值 x 是 2 的非负整数 n 次幂时,也就是 x = 2n,我们可以很容易地将 x 写成十六进制形式,只要记住 x 的二进制表示就是 1 后面跟 n 个 0。十六进制数字 0 代表 4 个二进制 0。所以,当 n 表示成 i + 4j 的形式,其中 0 ≤ i ≤ 3,我们可以把 x 写成开头的十六进制数字为 1(i = 0)、2(i = 1)、4(i = 2) 或者 8(i = 3),后面跟随着 j 个十六进制的 0。比如,x = 2048 = 211,我们有 n = 11 = 3 + 4 · 2,从而得到十六进制表示 0x800。
练习题 2.2
填写下表中的空白项,给出 2 的不同次幂的二进制和十六进制表示:
| n | 2n(十进制) | 2n(十六进制) |
|---|---|---|
| 9 | 512 | 0x200 |
| 19 | ||
| 16 384 | ||
0x10000 |
||
| 17 | ||
| 32 | ||
0x80 |
十进制和十六进制表示之间的转换需要使用乘法或者除法来处理一般情况。将一个十进制数字 x 转换为十六进制,可以反复地用 16 除 x,得到一个商 q 和一个余数 r,也就是 x = q · 16 + r。然后,我们用十六进制数字表示的 r 作为最低位数字,并且通过对 q 反复进行这个过程得到剩下的数字。例如,考虑十进制 314 156 的转换:
314 156 = 19 634 · 16 + 12 (C)
19 634 = 1 227 · 16 + 2 (2)
1 227 = 76 · 16 + 11 (B)
76 = 4 · 16 + 12 (C)
4 = 0 · 16 + 4 (4)
从这里,我们能读出十六进制表示为 0x4CB2C。
反过来,将一个十六进制数字转换为十进制数字,我们可以用相应的 16 的幂乘以每个十六进制数字。比如,给定数字 0x7AF,我们计算它对应的十进制值为:
7 · 16² + 10 · 16 + 15
= 7 · 256 + 10 · 16 + 15
= 1792 + 160 + 15
= 1967
练习题 2.3
一个字节可以用两个十六进制数字来表示。填写下表中缺失的项,给出不同字节模式的十进制、二进制和十六进制值:
| 十进制 | 二进制 | 十六进制 |
|---|---|---|
| 0 | 0000 0000 |
0x00 |
| 167 | ||
| 62 | ||
| 188 | ||
0011 0111 |
||
1000 1000 |
||
1111 0011 |
||
0x52 |
||
0xAC |
||
0xE7 |
旁注:十进制和十六进制间的转换
较大数值的十进制和十六进制之间的转换,最好是让计算机或者计算器来完成。有大量的工具可以完成这个工作。一个简单的方法就是利用任何标准的搜索引擎,比如查询:
把 0xabcd 转换为十进制数或
把 123 用十六进制表示
练习题 2.4
不将数字转换为十进制或者二进制,试着解答下面的算术题,答案要用十六进制表示。提示:只要将执行十进制加法和减法所使用的方法改成以 16 为基数。
A. 0x503c + 0x8 =
B. 0x503c - 0x40 =
C. 0x503c + 64 =
D. 0x50ea - 0x503c =