2.3 定点数的表示

无符号数与带符号数,原码、反码、补码、移码的定义与表示范围,C 语言中的整数类型转换、符号扩展,以及大端小端与边界对齐。

考查要求 ★★★ 重点掌握 原码反码补码移码表示范围无符号与有符号转换符号扩展大端与小端边界对齐

无符号数与带符号数

  • 无符号数:整个机器字长的全部二进制位均为数值位,没有符号位。nn 位无符号数的表示范围为 0∼2n−10 \sim 2^n - 1。
  • 带符号数:最高位用作符号位,“0”表示正,“1”表示负。根据数值位编码方式的不同,有原码、反码、补码和移码。
  • 计算机中的定点数分为定点整数(小数点隐含在最低位之后,纯整数)和定点小数(小数点隐含在符号位之后,纯小数)。

四种机器数

交互演示定点整数的原码、反码、补码与移码
① 由真值 -37 求各种机器数(最高位为符号位)[x]原10100101范围 ±(2^7−1) = ±127[x]反11011010负数:原码数值位取反[x]补11011011负数:反码 + 1;范围 −128 ~ 127[x]移01011011真值 + 2^7(偏置 128);与补码仅符号位相反
② 点击下面的位,观察同一个机器码在不同解释下的真值:
1706151403121100机器码= B6H
无符号数182原码−54反码−73补码−74移码54
补码的"模"为 2ⁿ:[x]补 = 2ⁿ + x(mod 2ⁿ)。快速求 −|x| 的补码:写出 |x| 的 n 位二进制(符号位为 0),从右往左找到第一个 1,这个 1 及其右边的 0 不变,左边各位(含符号位)全部取反。
编码正数负数nn 位整数的范围0 的表示
原码符号位 0 + 数值的绝对值符号位 1 + 数值的绝对值−(2n−1−1)∼2n−1−1-(2^{n-1}-1) \sim 2^{n-1}-1+0、−0 两种
反码同原码原码数值位取反−(2n−1−1)∼2n−1−1-(2^{n-1}-1) \sim 2^{n-1}-1+0、−0 两种
补码同原码反码 + 1−2n−1∼2n−1−1-2^{n-1} \sim 2^{n-1}-1唯一
移码真值 + 2n−12^{n-1}真值 + 2n−12^{n-1}−2n−1∼2n−1−1-2^{n-1} \sim 2^{n-1}-1唯一

C 语言中的整数

C 语言中 char、short、int、long 默认为带符号整数(补码表示),加 unsigned 修饰为无符号整数。

有符号数与无符号数的转换

C 语言允许在不同的数据类型之间做强制类型转换。在 int 与 unsigned int 之间转换时,位模式保持不变,只是解释方式改变:

short x = -4321;
unsigned short y = (unsigned short)x;   // x 的补码为 EF1FH,y = 61215

不同字长整数之间的转换

  • 长 → 短(截断):直接丢弃高位,保留低位。例如 int 型的 165537(0002 86A1H)转为 short 后为 86A1H = −31071。
  • 短 → 长(扩展):
    • 无符号数:零扩展,高位补 0;
    • 有符号数:符号扩展,高位补符号位。例如 short 型 −4321(EF1FH)扩展为 int 为 FFFF EF1FH,数值不变。

数据的存储与排列

大端与小端

现代计算机通常按字节编址,一个多字节数据(如 4 字节 int)占用多个连续的存储单元,其地址为最小的那个字节的地址。多字节数据在存储器中的排列方式有两种:

int x = 0x01234567,&x = 0x800大端(高位字节在低地址)01H23H45H67H小端(低位字节在低地址)67H0x80045H0x80123H0x80201H0x803
MSB 字节 01H(紫)与 LSB 字节 67H(青)的位置。x86 采用小端方式
  • 大端方式:先存储高位字节,后存储低位字节,字中的字节顺序与原序列相同(便于阅读);
  • 小端方式:先存储低位字节,后存储高位字节,字中的字节顺序与原序列相反(Intel x86 采用)。

在检查底层机器级代码时,需要分清大端/小端。例如 mov 0x12345678, %eax 在小端机器上的机器码中,立即数部分为 78 56 34 12。

边界对齐

假设存储字长为 32 位,可按字节、半字、字寻址。边界对齐要求:字地址为 4 的整数倍,半字地址为 2 的整数倍,以便一次访存就能取出一个完整的数据。这样做以空间换时间,减少访存次数。

C 语言中的 struct 也存在对齐问题:每个成员按其类型的大小对齐,结构体的总大小为最大成员大小的整数倍。

struct { char a; int b; short c; } s1;   // 1 + 3(填充) + 4 + 2 + 2(填充) = 12 字节
struct { int b; short c; char a; } s2;   // 4 + 2 + 1 + 1(填充) = 8 字节

即时练习

即时练习5 题
点击选项即可作答
  1. 1
    假定有 4 个整数用 8 位补码分别表示为 r1 = FEH,r2 = F2H,r3 = 90H,r4 = F8H。若将运算结果存放在一个 8 位寄存器中,则下列运算会发生溢出的是( )。
  2. 2
    有如下 C 语言程序段:
    short si = -32767;
    unsigned short usi = si;
    执行上述两条语句后,usi 的值为( )。
  3. 3
    某计算机字长为 32 位,按字节编址,采用小端方式存放数据。假定有一个 double 型变量,其机器数表示为 1122 3344 5566 7788H,存放在 0000 8040H 开始的连续存储单元中,则存储单元 0000 8046H 中存放的是( )。
  4. 4
    若 x = 103,y = −25,则下列表达式采用 8 位定点补码运算实现时,会发生溢出的是( )。
  5. 5
    8 位移码 1000 0000 表示的真值是( )。
学完了吗?

标记完成后,侧栏会显示进度。进度仅保存在本浏览器中。