日期:2014-05-16  浏览次数:20637 次

无符号在计算机中的操作过程
前段时间大脑短路,碰到一个有关无符号翻转的问题。先将我的理解写出来,如有不对的,欢迎拍板砖啊。

    大家都知道类型有有符号和无符号之分,顾名思义有符号有负数表示,而无符号只有正数。如果判断一个无符号变量小于0,就会出现错误,特别是在循环中,会陷入死循环。例如:
    unsigned int i; 
    for(i=9;i>=0;i--)
        printf("%u",i);
执行这个程序,会不停的打印出i,直到cpu累了或者是断电才会停止。为什么会出现这种情况?我i不停的变小就不可能小于0吗?恭喜你答对了,永远不可能小于0。你要问为什么,答案就是,i是一个无符号变量,而无符号不可能是负的,如果是无符号当然无可厚非,会输出你想要的结果。
    实际上计算机是不知道有符号无符号的,这完全是人类为了方便计算而想出来的方法。不管正负,计算机都老老实实的用1和0去表示和计算,进行加减运算时(实际上减法也会当做加法进行运算),都会以补码的形式进行计算,编译器会根据我们指定的类型给出我们结果(比如以无符号输出就用%u)。所以上面例子中,每次都加-1,而-1在计算机中的表示为8个F(也就是32个1),当加到0的时候再加-1结果为16个1,这时候如果你以无符号形式输出的时候就翻转为无符号最大值了(注意是无符号,32位都表示值)。当从最大值减到0的时候又会重复上面的过程。而FFFFFFFF减1再取反就是-1了。
------解决方案--------------------
楼主只要记住,二进制摆在那里,是不会变的。

只有是同宽变量互相=赋值,都是二进制拷贝,二进制是不会变的,怎么解析是编译器的事。

不同宽的变量互相=赋值,长的按照二进制截短(与字节序无关),短的扩宽(根据短变量有无符号,填充符号位/填充0)


------解决方案--------------------
有符号与无符号只是表现形式,而不是存储形式,LZ一定要区分什么是给人看的,什么是给计算机看的……
简单来说,(1010 0101)补 的真值是多少?不知道,这是一个存在二义性的数字,即可以认为是十进制的-179,也可以认为是十进制的325,关键就在于你怎么去解析它……
至于LZ所说的减法,不好意思,计算机不会算减法,计算机只会先把一个负数变成补码,然后算补码加法,至于加完以后怎么样,计算机就不管了,因为怎么解析并不是计算机的工作……
如果LZ想把这个事情彻底弄明白,最简单的办法就是去看计算机组成原理,定点数运算这部分内容,这里面会解决你所有的疑问,你会清楚的了解cpu每一步的操作过程,以及数制转换关于整数部分的全部内容……
------解决方案--------------------
无符号整型数做0减1的机内操作就是,0+0xffff=0xffff,所以依然大于0.
------解决方案--------------------
引用:
无符号整型数做0减1的机内操作就是,0+0xffff=0xffff,所以依然大于0.


看二进制