1. ⼆进制
其实我们经常能听到2进制、8进制、10进制、16进制这样的讲法,那是什么意思呢?其实2进制、8进 制、10进制、16进制是数值的不同表⽰形式⽽已。
⽐如:数值15的各种进制的表⽰形式:
我们重点介绍⼀下⼆进制:
⾸先我们还是得从10进制讲起,其实10进制是我们⽣活中经常使⽤的,我们已经形成了很多尝试:
• 10进制中满10进1
• 10进制的数字每⼀位都是0~9的数字组成
其实⼆进制也是⼀样的
• 2进制中满2进1
• 2进制的数字每⼀位都是0~1的数字组成
那么 1101 就是⼆进制的数字了。
(1) 2进制转10进制
其实10进制的123表⽰的值是⼀百⼆⼗三,为什么是这个值呢?其实10进制的每⼀位是权重的,10进 制的数字从右向左是个位、⼗位、百位....,分别每⼀位的权重是 10 , 10 , 10 ... 0 1 2
如下图:
2进制和10进制是类似的,只不过2进制的每⼀位的权重,从右向左是: 2 , 2 , 2 ... 0 1 2 如果是2进制的1101,该怎么理解呢?
(i)10进制转2进制数字
(2)2进制转8进制和16进制
(i)2进制转8进制
8进制的数字每⼀位是0~7的,0~7的数字,各⾃写成2进制,最多有3个2进制位就⾜够了,⽐如7的⼆ 进制是111,所以在2进制转8进制数的时候,从2进制序列中右边低位开始向左每3个2进制位会换算⼀ 个8进制位,剩余不够3个2进制位的直接换算。
如:2进制的01101011,换成8进制:0153,0开好头的数组,会被当做8进制。
(ii)2进制转16进制
16进制的数字每⼀位是0~9,a ~f 的,0~9,a ~f的数字,各⾃写成2进制,最多有4个2进制位就⾜够了, ⽐如 f 的⼆进制是1111,所以在2进制转16进制数的时候,从2进制序列中右边低位开始向左每4个2进 制位会换算⼀个16进制位,剩余不够4个⼆进制位的直接换算。
如:2进制的01101011,换成16进制:0x6b,16进制表⽰的时候前⾯加0x
2. 原码、反码、补码
整数的2进制表⽰⽅法有三种,即原码、反码和补码
三种表⽰⽅法均有符号位和数值位两部分,符号位都是⽤0表⽰“正”,⽤1表⽰“负”,⽽数值位 最⾼位的⼀位是被当做符号位,剩余的都是数值位。
正整数的原、反、补码都相同。
负整数的三种表⽰⽅法各不相同。
原码:直接将数值按照正负数的形式翻译成⼆进制得到的就是原码。
反码:将原码的符号位不变,其他位依次按位取反就可以得到反码。
补码:反码+1就得到补码。
对于整形来说:数据存放内存中其实存放的是补码。
为什么呢?
3. 移位操作符
<< 左移操作符
>> 右移操作符
注:移位操作符的操作数只能是整数。
(1)左移操作符
移位规则:左边抛弃、右边补0
(2)右移操作符
移位规则:⾸先右移运算分两种:
逻辑右移:
算术右移:
警告⚠️:对于移位运算符,不要移动负数位,这个是标准未定义的。
例如:
int num = 10;
num>>-1;//error
4. 位操作符:&、|、^
位操作符有:
& //按位与
| //按位或
^ //按位异或
//注:他们的操作数必须是整数。
直接上代码:
#include <stdio.h>
int main()
{
int num1 = -3;
int num2 = 5;
num1 & num2;
num1 | num2;
num1 ^ num2;
return 0;
}
⼀道变态的⾯试题:
#include <stdio.h>
int main()
{
int a = 10;
int b = 20;
a = a^b;
b = a^b;
a = a^b;
printf("a = %d b = %d\n", a, b);
return 0;
}
练习:编写代码实现:求⼀个整数存储在内存中的⼆进制中1的个数。
//参考代码:
//⽅法1
#include <stdio.h>
int main()
{
int num = 10;
int count= 0;//计数
while(num)
{
if(num%2 == 1)
count++;
num = num/2;
}
printf("⼆进制中1的个数 = %d\n", count);
return 0;
}
//思考这样的实现⽅式有没有问题?
//⽅法2:
#include <stdio.h>
int main()
{
int num = -1;
int i = 0;
int count = 0;//计数
for(i=0; i<32; i++)
{
if( num & (1 << i) )
count++;
}
printf("⼆进制中1的个数 = %d\n",count);
return 0;
}
//思考还能不能更加优化,这⾥必须循环32次的。
//⽅法3:
#include <stdio.h>
int main()
{
int num = -1;
int i = 0;
int count = 0;//计数
while(num)
{
count++;
num = num&(num-1);
}
printf("⼆进制中1的个数 = %d\n",count);
return 0;
}
//这种⽅式是不是很好?达到了优化的效果,但是难以想到。