下面只是记录自己的不懂的地方。
在笔试中遇到的问题,才发现这个问题没有搞清楚。
首先介绍 原码,补码,反码。
正数的原,反,补码 相同。
负数:原码就是正数的原码,最高位为1;补码:除符号位取反;补码:反码+1**
比如说 -2的原码:1000 0010,反码:1111 1101 补码:1111 1110。
-1的补码:1111 1111。-128的补码:1000 0000,-128没有原码和反码
为解决原码减法问题,引入反码,但是反码引入了+0和-0的问题。
1-1=0
1 - 1 = 1 + (-1)
= [0000 0001]原 + [1000 0001]原
= [0000 0001]反 + [1111 1110]反
= [1111 1111]反 = [1000 0000]原
= -0
解决反码的+0和-0问题,引入补码问题。这样-0的表示为-128
(-1) + (-127) = [1000 0001]原 + [1111 1111]原
= [1111 1111]补 + [1000 0001]补
= [1000 0000]补
=-128
类型的范围
char:-128 — 127 一共256个数
unsigned char : 0 —255 一共256
short:-32768—32767
unsigned short:0—65535
int 2147483648~2147483647
unsigned int 0~4294967295
有符号和无符号的计算
当有符号和无符号计算时,有符号会提升成无符号计算。
例题1、
unsigned int a = 12;
int b = -14;
cout <<a+b<<endl;
分析:
12 - 14
= [0000 0000 0000 1100]原 + [1000 0000 0000 1110]原
= [0000 0000 0000 1100]补 + [1111 1111 1111 0010]补
= [1111 1111 1111 1110]补
但是结果是无符号的,在计算机中数字存储的是补码存放的。
所以将上面的数字看出无符号的,[1111 1111 1111 1110]看做无符号的整数,
正好为unsigned int 的最大范围-1:4294967294
例题2、
int a = -25;
a = a >> 2;
cout << a << endl;
a的原码:1000 0000 0001 1001
补码: 1111 1111 1110 0111
向右移2位:[1111 1111 1111 1001]补码
原码:【1000 0000 0000 0111】=-7。
例题3、
union test
{
char m[4];
int a;
};
test t;
t.a = 0x00ffffaa;
printf("%d\n", t.m[0]);
小端存储:低位存放到低地址处。
联合体:char m[4]:从m[0],m[1],m[2],m[3];也是低地址到高地址
所以m[0]存放的是低位aa
计算机中存储的补码:1010 1010
原码:1101 0110 为-86。