1. 信息存储

计算机使用字节作为最小的内存寻址单位,1 个字节等于 8 位。机器级程序将内存视为一个非常大的字节数组,称为虚拟内存。内存的每个字节都用唯一的数字来标识,称为它的地址。所有可能地址的集合称为虚拟地址空间。这个地址空间只是一个展现给机器级程序的概念性映像。

我们一般不直接使用 0 和 1 表示信息,那样的话数据太长了,而且可读性不好。通常把四个二进制当作一组,也就是十六进制表示字节,以 0x 或 0X 开头的数字代表十六进制的值,两个十六进制的值就是一个字节。比如:01011100 等价于 5C。

十六进制表示法

字节用十六进制表示后,下面该确定它的顺序了。内存地址是递增的,是按照人类的习惯,高位在前低位在后,还是相反呢?

字节的排列方式有两种:

  • 大端法(big endian):最高有效字节在前
  • 小端法(little endian):最低有效字节在前

举个例子:0x01234567

地址 0x100 0x101 0x102 0x103
大端法 01 23 45 67
小端法 67 45 23 01

选择何种字节顺序,并没有技术上的优劣之分,只要坚持使用同一种规则。

参数 12345 的十六进制表示为 0x00003039,下面是在不同系统上测试的结果。

不同数据值的字节表示

从上图可以看出,Linux 32、Windows 和 Linux 64 采用小端法表示,Sun 采用大端法表示。

2. 整数表示

C 语言的整数分为无符号数和有符号数,而 Java 只有有符号数。

无符号数的所有位都表示值,对于 w 位长度的无符号数,它的取值范围是 0 - 2^w-1,编码表示是唯一的。举个例子:

1011 = 1 * 2^3 + 0 * 2^2 + 1 * 2^1 + 1 * 2^0 = 11

有符号数采用补码表示,最高位是符号位,其中 1 代表负数,0 代表正数。对于 w 位长度的无符号数,它的取值范围是 -2^(w-1) - 2^(w-1),编码表示是唯一的。举个例子:

1011 = -1 * 2^3 + 0 * 2^2 + 1 * 2^1 + 1 * 2^0 = -5

重要的数字

其中,U 表示最无符号编码,T 表示补码编码。

有符号数到无符号数的隐式类型转换导致某些非直观的行为,避免这类错误的一种方法是绝不使用无符号数。

总结一下:

  • 计算机用二进制表示信息,我们把计算机的二进制用十六进制表示是更友好的升华。
  • 字节的排序方式有两种:大端法和小端法,区别是高位在前还是在后。
  • 无符号数的所有位表示值。
  • 有符号数采用补码表示,最高位是符号位。
  • 无符号数和有符号数之间的转换容易出错,尽量避免使用无符号数。