一.原码,补码和反码 计算机只能存储0和1,因此在计算机中,数字是采用二进制表示的。 例如看看计算机是如何存储数字5的: 5在内存中的为:0x00000005(采用的16进制表示) 而转换为二进制为:0000 0000 0000 0000 0000 0000 0000 0101 共32位,这个称为5的原码 而计算机CPU中,是只能进行加法功能的,减法的计算都是形如“2+(-5)”的形式进行的 下面我们看看计算机是如何存储-5的: 方法为:计算机要对数字”5“取反,再加1 对5取反为:1111 1111 1111 1111 1111 1111 1111 1010 再加1为:1111 1111 1111 1111 1111 1111 1111 1011 在内存中(16进制)即为0xfffffffb,称为补码 对于补码:1.正数的补码就是其本身 2.负数的补码是在其原码的基础上, 符号位不变, 其余各位取反, 最后加1 3.负数在内存中就是以补码形式存储的 对-5加2得 1111 1111 1111 1111 1111 1111 1111 1011(-5) + 0000 0000 0000 0000 0000 0000 0000 0010(2) ----------------------------------------- 1111 1111 1111 1111 1111 1111 1111 1101 在内存中(16进制)即为0xfffffffd 注:1.1111=1*(2^3)+1*(2^2)+1*(2^1)+1*(2^0)=15 在16进制中为'f'; 1101同理,为13, 即16进制中的‘d’ 2. 对于有符号常数,最高位就是符号位,符号位是1,就是负数,如果为0就是正数。 负数的补码是在其原码的基础上, 符号位不变, 其余各位取反, 最后加1。 但是需要注意的是,在考研的时候一般通过8位表示,比如-5 就是1111 1011来表示 反码:反码就是在计算机中数的机器码表示,对于单个数字而言,正数的反码是其本身,负数的反码是在其原码的基础上, 符号位不变,其余各个位取反。 二.符号数和无符号数的运算 我们再看下面一个例子: 两个无符号数字 unsigned int a=134;unsigned int b=246; unsigned x=a-b; 那么此时该如何计算呢? 对于134的2进制:1000 0110 而对于246,虽然是无符号数字,但是在计算的时候仍然可以取反加1来计算 246:1111 0110 取反加一后为:0000 1010 134-246=1000 0110+0000 1010=1001 0000=90H 这里不用管他是负数啥的,可以理解为取了绝对值 那么再看这样一个操作:unsigned int a=134; int m=a; 那此时的m的值是多少呢? 因为a是一个无符号数变成了一个有符号数 所以a=134:1000 0110 的最高位就变成了一个符号位,所以m是一个负数 求m就要让a取反加1,得m的绝对值。 a取反加1的结果位(1)111 1010=122,所以m就是-122 符号数的加减和无符号数的加减用的是同一个加法器 三.逻辑移位和算数移位 逻辑移位:左移和右移空位都补0,所有数字参与计算 算数位移:符号位不移动,右移空位补符号位,左移空位补0 四.整型溢出 由上面的知识可知,因为有符号整型数据和无符号整型数据,由于他们的最高位代表的意义不同,所以两者能代表的数字的范围不同, 超出范围会发生溢出现象,导致计算错误。 我们看下面一个例子:
#include<stdio.h>
int main()
{
short a=32767;
short b=0;
b=a+1;
printf("%d",b);
return 0;
}
运行这个代码会发现,b=a+1,输出的结果变成了-32768,从一个正数变成了负数。 这是因为32767对应的内存位0x7fff,加1后变成了0x8000,最高位由0变成了1,因此变成了一个负数。 而运行这个代码:
#include<stdio.h>
int main()
{
unsigned a=32767;
unsigned b=0;
b=a+1;
printf("%d",b);
return 0;
}
输出结果为32768,此时就是正确的,因为无符号整型数最高位不代表正负。
判断带符号整型数加/减溢出:
符号位和数据高位(即除了符号位的最高位)没有同时进位或者没进位,就会发生溢出
考研会考8位的,也就是一个字节的整型数大小,对于一个字节的有符号类型的数值范围是-128~127,而无符号数则是0~255
(因为对于short来说,是16位,2字节,所以是-2^(16-1)~2^(16-1)-1;变成了8位,1字节,就是把16变成了8)
(因为对于int 来说,是32位,4字节,一样要除以指数要除以4)
(个人笔记,如有错误,感谢指正)