2.2.4 十六进制计数系统
二进制表示法实在很冗长,由于读和写二进制数值都很麻烦,程序员们通常都避免在程序源文件中使用二进制表示法,而更喜欢用十六进制符号。十六进制表示法有两个非常好的特性:它很紧凑,而且在二进制与十六进制间换算非常容易。因此,为了让程序更好读,软件工程师一般使用十六进制表示法而不是二进制表示法。
由于十六进制表示法的基数为16,十六进制小数点(hexadecimal point)左边的每个数字都表示了某个值乘以16的连续递增的幂。例如,数123416等效于:
|
1 × 16 3 + 2 × 162 + 3 × 161 + 4 × 160 |
或者
|
4096 + 512 + 48 + 4 |
或者
|
466010 |
十六进制表示法使用字母A到F来表示所需的六个额外数字(在十个标准十进制数字0-9之外,之上)。以下是一些合法的十六进制数的例子:
|
23416 DEAD16 BEEF16 0AFB16 FEED16 DEAF16 |
2.2.4.1 程序语言中的十六进制表示
十六进制表示法的问题在于很难将“dead”这样的十六进制值与标准的程序标识符区分开来。因此,大多数程序设计语言使用特殊的前缀或者后缀字符来表示源文件中的十六进制常量。以下就是在几种常用语言中表示十六进制常量的方法:
l C,C++,C#,Java以及其他从C语言衍生而来的程序设计语言都使用前缀“0x”来表示十六进制数值。因此,在这些语言中,字符序列“0xdead”表示十六进制数值DEAD16。
l MASM汇编程序使用后缀“h”或者“H”来表示十六进制数值。这还不足以消除某些标识符与十六进制常量之间的二义性问题,对于MASM来说,“deadh”看起来还是像一个标识符。因此,MASM还规定十六进制数必须以数字开始。这导致了对于非数字开始的十六进制数,需要在其前面增加一个“0”(在任一种数值表示前面添加零不会改变该数值表示的值)例如,使用“0deadh”来明确表示十六进制数值DEAD16。
l Visual Basic使用前缀“&H”或者“&h”来表示十六进制数值,对于我们一直在使用的例子(DEAD16),在Visual Basic中使用“&Hdead”来表示。
l Pascal(Delphi/Kylix)使用符号$作为前缀来表示十六进制数。因此对于以上的例子而言,在Delphi/Kylix中,它的表示就是“$dead”。
l HLA也使用符号$作为前缀来表示十六进制数值。因此在HLA中一样是使用“$dead”来表示DEAD16。HLA还允许在十六进制数值中间插入下划线来提高可读性,例如“$FDEC_A012”。
本书主要使用HLA/Delphi/Kylix的方式来表示十六进制数,除非使用的例子是特定于其他某种程序设计语言的。因为本书有一些C/C++的例子,所以C/C++的例子也很常见。
2.2.4.2 十六进制表示法与二进制表示法的互相换算
不仅因为十六进制表示法易于在代码中紧凑地表示数值,十六进制表示法流行的原因还在于它与二进制表示法间的换算非常方便。只需记住几条简单的规则,你就能使用心算来在两种表示法之间进行换算,请看表2-1。
表2-1 二进制/十六进制换算表
|
二进制 |
十六进制 |
|
%0000 |
$0 |
|
%0001 |
$1 |
|
%0010 |
$2 |
|
%0011 |
$3 |
|
%0100 |
$4 |
|
%0101 |
$5 |
|
%0110 |
$6 |
|
%0111 |
$7 |
|
%1000 |
$8 |
|
%1001 |
$9 |
|
%1010 |
$A |
|
%1011 |
$B |
|
%1100 |
$C |
|
%1101 |
$D |
|
%1110 |
$E |
|
%1111 |
$F |
为了将一个数的十六进制表示换算为二进制,只需将每个十六进制数字替换为相对应的四个二进制位。例如,为了将%ABCD换算为二进制表示%1010_1011_1100_1101,只需要使用表2-1来将十六进制数位进行换算:
|
A |
B |
C |
D |
十六进制 |
|
1010 |
1011 |
1100 |
1101 |
二进制 |
将二进制表示的数换算为十六进制也很容易。首先是对二进制数用零进行(左)填充,保证其长度是4的倍数。例如,对于二进制数1011001010,第一步是在其左边加上两个零,使其长度为12个位,而且它的值保持不变,结果是001011001010。下一步就是
将二进制值划分为4位一组:0010_1100_1010。最后,在表2-1中查询这些二进制数,并用对应的十六进制数字来替换,结果就是$2CA。对比一下,十进制与二进制以及十进制与十六进制的换算是多么困难!






