今天带大家复习一个容易遗忘的C语言知识点,负数的存储和典型的排查形式。先看一个题目#includeintmain(){inta,b,c,d;//或inta,b,c,d;a=0x8;b=a>>1;c=~(~0<<1);d=b&c;printf("cis%d\n",c);printf("dis%d\n",d);}解析:假设计算机存储8个00b00000000~bitwiseinversion0b11111111左移一位0b11111110用0补空位然后bitwiseinvert0b00000001所以c等于1这里是一步步推导出来的,你会忽略一个关键过程,就是你计算的~0是的,就是0b11111111,一个很大的负数,这有悖于你认为的常识,下面我们来讨论。再举个例子#includeintmain(){printf("~0==%d\n",~0);}0的存储是0b00000000~按位取反0b11111111这道题比较直白,直接~0==-1,有时候我们不明白为什么0b11111111在内存中代表-1,因为反正是一个非常大的负数。但实际上,负数在内存中是以补码的形式存储的,也就是说0b11111111是补码,那么它的反码就是0b11111110,原码就是0b10000001,就是-1(注意负数补码时符号位不变)结论0b11111111==-1(~0)0b11111110==-2(~1)0b11111101==-3(~2)可以看做asaformula~a==-[a+1]补充说明为什么整数要以二进制补码形式存入内存。因为正数的原码和补码是一样的,所以我们主要讨论负数为什么要以补码的形式存入内存。使用补码的原因或好处如下。使用补码运算有以下两个特点:1)因为使用补码可以把符号位和其他位统一对待,同时减法也可以当加法处理,即如果是complementcode表示的数,不管是加法还是减法,都可以直接通过加法运算来实现。2)两个用补码表示的数相加时,如果最高位(符号位)有进位,则舍去进位。这样的运算有两个好处:1)符号位可以和有效值部分一起参与运算,从而简化了运算规则。因此,可以简化计算器的结构,提高计算速度。(减法可以用加法表示)2)加法比减法更容易实现。将减法运算转化为加法运算,进一步简化了计算机中运算器的电路设计。下图最能说明为什么整数的减法(即负数的运算)可以用补码变成加法:深入证明:与带符号位的原码乘除的结果是正确的,但是在加减法的时候出现了问题,如下:假设字长为8bits(1)-(1)=(1)+(-1)=(0)可以表示为:(00000001)original+(10000001)original=(10000010)original=(-2)显然是不正确的。。因为两个整数相加没有问题,发现问题出在带符号位的负数上,而除符号位之外的其余位的逐位反转产生反码。反码的值空间与原码相同,一一对应。下面是反码的减法运算:(1)-(1)=(1)+(-1)=(0)可以表示为:(00000001)反码+(11111110)反码=(11111111)反码=(-0)有问题。(1)-(2)=(1)+(-2)=(-1)可以表示为:(00000001)reverse+(11111101)reverse=(11111110)reverse=(-1)正确的问题出现在(+0)和(-0),零在人们的计算概念中没有正负之分。于是引入了补码的概念。负数的补码是在补码上加一,而正数不变,正数的原码的补码是一样的。在补码中,用(-128)代替了(-0),所以补码的表示范围为:(-128~127),共256个。注:(-128)没有对应的原码码和反码。(-128)=(10000000)补码的加减法如下:(1)-(1)=(1)+(-1)=(0)可表示为:(00000001)补码+(11111111)补=(00000000)补=(0)正确(1)-(2)=(1)+(-2)=(-1)可以表示为:(00000001)补+(11111110)补=(11111111)complement=(-1)正确使用补码表示还有一个原因,就是防止0的机器号有两个码。原码和反码表示的0有+0和-0两种形式,我们知道+0和-0是一样的。这样,8位原码和反码表示的整数范围为-127-127(11111111-01111111),用补码表示时,00000000为+0,即0;10000000不再是-0,而是-128。这样,补码表示的数的范围为-128~+127,既增加了表示数的范围,又保证了0码的唯一性。为什么一个正数的反码,补码和原码一样?这是规则或协议。理由不多,想不通。求补只是负数的一种想法,目的是变减法为加法。是的,减法可以通过补码来实现。补码加1即可得到补码。所以道又有负数的倒数。计算机中有一个硬件“加法器”。有了补数,减法也可以用加法器来完成。计算机的计算速度是硬件比软件快很多。这就是想出一个人的补充,补充和独创的技巧。图片说明引入补码的作用是让计算机更容易做减法。比如时间是12小时,当前准确时间是4点钟,有表显示是7点钟。校准时间,我们可以将时针向后移动7-4=3格,或者向前移动12-3=9格,计算机减法后可以转换为-3=+9,可以简化硬件设备计算机做复杂的减法。