虽然一直用C/C++,但很少涉及到Bit序列的问题。比如,-1的二进制表示到底是怎样的?从没有深究过,一直都是模棱两可的,说出来实在让人笑话。
对于有符号整型数的简单认识就是,最高位为符号位,0为正,1为负,那么剩下几位应该如何表示呢?理所当然的认为,既然是1表示为0000 0001(假设为8位整型数,下同),那么-1就应该表示为1000 0001了。
但是,在C语言里,-1的正确表示应该是1111 1111,即0xFF。因为C语言里,对整型数是采用Two’s complement表示法,而前面我的理解则是Sign-Magnitude表示法(浮点数采用该法)。在Two’s complement表示法里,1000 0001表示的是-127。
几个特殊值,比如:正值的最大表示为0111 1111,即127。负值的最小表示为1000 0000,即-128。
并因此带来几个有趣的现象,比如从8位有符号数转成16位有符号数的填充问题。以前想当然的是填0,但这是错的,应该是填充符号位的值。比如-1=0xFF填充符号位1就应该变成0xFFFF。而如果填充的是0,那么变成0x80FF就不对了。
Two’s complement是不对称的。一个数的正负值表示,除了最高位之外,其余位数也是不尽相同的。在C语言里,当在无符号数和有符号数之间进行转换的时候,数值的二进制序列是不会改变的,改变的只是对该序列的解读模式。比如有符号数-1转换成无符号数就变成了255,虽然其二进制表示都是0xFF。如果不理解这一点,就会出Bug。
对于C/C++程序员,的确有必要研读《深入理解计算机系统》(Computer Systems: A Programmer's Perspective)。