C的二进制表示

来源:互联网 发布:怎么查自己的淘宝账号 编辑:程序博客网 时间:2024/05/20 20:22

对于有符号整型数的简单认识就是,最高位为符号位,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。


补码运算:正数为原码本身,负数为原码取反加一 
127为正数,其补码为原码0111 1111 
-127为负数,其补码为原码0111 1111,取反1000 0000,加一,1000 0001。 

根据这情况来看,表示-0,不是的,-0的原码是1000 0000补码是0000 0000。+0的补码也是0000 0000 

于是就有了规定 1000 0000 定为 -128的补码 
这种定法和上面数学层面的表述是一致的。 
这样规定后,负数的补码在机器中就好算了。 
在约定的范围内(-128-+127,对16位32位64位等扩大范围) 
先将该负数取绝对值,再用二进制表示出这个绝对值 (不管符号位) 对该二进制数进行取反加一操作就得到负数的补码了 
-128 绝对值是 128 
128的二进制表示为: 
1000 0000 
取反 
0111 1111 
加1 
1000 0000 
这就是-128的补码 
这种办法算出的结果符合“规定值”,规定而已。 

0 0