十进制数据转换成补码:
正数:原码就是补码
负数:
1、计算它的绝对值二进制数据得到原码
2、原码按位求反得到反码
3、反码+1得到补码
char num = -116; -128
printf("%hhd\n",num-34);
01110100 116原码
10001011 反码
10001100 -116补码
00100010 34原码
11011101 反码
11011110 补码
10001100 -116补码
01101010
64+32+8+2 = 106
00000000 00000000 00000000 00100010
11111111 11111111 11111111 11011101
11111111 11111111 11111111 11011110 -34
11111111 11111111 11111111 10001100
11111111 11111111 11111111 01101010
11111111 11111111 11111111 01101001 反码
00000000 00000000 00000000 10010110 -150
128 + 16 + 4 + 2
补码转换成十进制数据:
1、判断补码是否是有符号的,如果是无符号补码直接转换成十进制即可。
2、有符号的补码需要根据符号位,判断是不正数还是负数。
3、最高位如果是0,则说明是正数的实补码直接转换成十进制即可。
4、最高位如果是1,则说明是负数的实补码,补码-1得到反码,反码按位求反得到原码,原码转换成十进制数据并加负数。
注意:在有限的二进制位中,最小值减1就会变成最大值,而最大值加1就会变成最小值。
-128 + -1
10000000
01111111
10000000
00000001
11111110
11111111
11111111 + 10000000 = 01111111
常考笔试题:以下循环会执行多少次。
for(char i=-111; i<10; i--)
{
//
}
1、字符型变量不能当作循环变量,编译出错。
2、编译能通过,但运行会进入死循环。
3、17次
4、18次
解析:当i的值逐渐变成最值后,再自减1就会变成char类型的最大值127,此时会结束循环。
练习1:实现一个函数,用于显示一个整数的补码。
void show_bit(int num);
位运算符:
位运算符是对数据的补码进行运算。
& 对应的二进制位进行与运算
-125 & 34
01111101 -125原码
10000010 反码
10000011 -125补码
00100010 34补码
00000010 结果是2
| 对应的二进制位进行与运算
-125 | 34
01111101 -125原码
10000010 反码
10000011 -125补码
00100010 34补码
10100011 %hhu 163 %hhd 10100010 01011101 -93
~ 对每个二进制位进行求反,单目运算符
~-125
01111101 -125原码
10000010 反码
10000011 -125补码
01111100 124
^ 按位异或运算符
对应的二进制位如果相同得的是1,如果不同得到的是0。
-125 ^ 34
01111101 -125原码
10000010 反码
10000011 -125补码
00100010 34补码
10100001 异或运算得到结果的补码
10100000 结果反码
01011111 结果原码-95
A ^ B = C
C ^ B = A
C ^ A = B
<< 左移
n << m 把n的前m个二进制位删除掉,在末尾增加m个0。
-125 << 4
01111101 -125原码
10000010 反码
10000011 -125补码
00110000 结果是48
>> 右移
n >> m 先判断n是否是有符号数据。
n是有符号补码:把n末尾的m个二进制位删除掉,前面增加m个符号位。
n是无符号补码:把n末尾的m个二进制位删除掉,前面增加m个0。
-125 >> 4
01111101 -125原码
10000010 反码
10000011 -125补码
11111000
11110111
00001000 -8
int num = -1 , cnt = 0;
while(num)
{
num = num&(num-1);
cnt++;
}
printf("%d",cnt);
练习2:实现一个函数,用于显示一个整数的补码(使用位运算符解决)。