二进制补码的特性

设一个w位数值的二进制位从高到低依次为:[xw-1, xw-2, …, x1, x0],那么这个数所表示的有符号数的数值V为:

 

这就是二进制补码表示有符号数时,数值跟位模式之间的关系定义。

16位有符号数为例,如果把位模式0x0000跟位模式0xffff,首尾相接,从而构成一个环形,那么二进制补码相当于把这个环从0x8000的地方剪开,从而0x00000x7fff这半圈继续留在上面表示非负数,而0x80000xffff这半圈从剪开的地方开始落下,落到下面表示负数,其中0xffff仍然紧连在0x0000之下表示-1,而0x8000则跌落谷底成了最小的-32768。需要注意的是:数值的递增方向跟原环中数值的递增方向是一致的,也就是说,并没有因为要表示负数而导致了数值递增方向相反的两个半圈。

C语言是一种较接近机器底层的语言,但它的语言标准中并没有规定有符号数要用二进制补码来表示;可事实上几乎所有平台上有符号数都是用二进制补码来表示,它已成为“事实上的标准”,这无疑源于二进制补码巧妙的设计,这种巧妙使得用它来表示有符号数时会带来很多有用的或有趣的特性,比如:

10值唯一。用补码表示有符号数,0有唯一的表示:0x0000,不像其它一些码制(如原码、反码),有+0-0之分;

2)最高位有符号位的功能。最高位为1的必为负数,为0的必为非负数;

3)有符号数的表示范围:[-2w-1, 2w-1)

4)加法运算在位模式上与无符号数完全一致(包括溢出的情形)。处理器中只需一套加法电路便可同时处理无符号数和有符号数的加法运算;

5)乘法运算在位模式上与无符号数完全一致(包括溢出的情形)。处理器中只需一套乘法电路便可同时处理无符号数和有符号数的乘法运算;

6)数值x按位取反后再加1,即得其相反数-x。由于减去一个数等于加上其相反数,因此处理器中只要有加法电路,做减法就已经是小菜小碟;

7)自增运算在位模式上与无符号数完全一致。不论是有符号数还是无符号数,有符号时也不论是正数还是负数,增1运算都可以同样处理:找到最右边一个为0的位,从这一位向右一直到最后一位依次取反(即011……变成100……)即可。

8)扩展数位时只需扩展符号位,可保证数值不变。比如一个16位有符号整数扩展为一个32位有符号数时,只需把前面新增的16位设为跟原来的最高位相同的模式;

9)乘以2K次幂(0 ≤ K < w),只需左移K位,与无符号数一致;

10)整除2K次幂(0 ≤ K < w,只需把原来的数向右做“算术右移”,右移K位;算术右移是指左边补最高位(而非补0)的右移运算。

 

最后,关于这些特性,本文只说结论,理论上的推导过程可参考《Computer Systems: A Programmer’s Perspective》,第2章。

你可能感兴趣的:(c,扩展,语言,平台)