文章目录
1.移位操作符(针对整形):
1.1.左移操作符(<<):
规则:左抛弃,右补0。
1.2.右移操作符(>>):
规则:1.算数右移:左补0,右丢弃。
2.算数右移:左补符号位,右丢弃。
--------------------------------------------逻辑右移-------------------------------------------------
--------------------------------------------算数右移-------------------------------------------------
2.位(二进制位)操作符:
2.1.按位与(&)
规则:两个二进制数同一位为1,进行按位与操作后同位得到1,其余情况均为0。(类似于逻辑中的并)
引申:
a.一个整数按位与1只能得到0或1,等于0时(二进制)最低位为0,等于1时二进制最低位为1。由此可检验一个数的二进制最低位是否为1或者是检验奇偶性。
b.按位与可以实现二进制位1->0,无法实现0->1。(逻辑中:两个操作数只要有一个为假,结表达式果必为假)。
c.n按位与n-1可以实现n的二进制数位中的一个1变为0(从右往左)。如下例:
求⼀个整数存储在内存中的⼆进制中1的个数。
注:我们应该明确一个整数在内存中存储的是二进制补码(后文将会详细介绍)。
实现方法:
Way1:(整体)移位计数法
思路:二进制最后一位为一(是奇数)则计数一次。将该数除以2,相当于二进制位整体向右移动一位(这里也跟整数除法相呼应:奇数除以二余数舍弃1,偶数除以二相当于余数舍弃0)
#include <stdio.h>
int main()
{
int num = 10;
int count= 0;//计数
while(num)
{
if(num%2 == 1)
{
count++;
}
num = num/2;//可改为num=num>>1;
}
printf("⼆进制中1的个数 = %d\n", count);
return 0;
}
缺点:无法处理负数的问题。
Way2:数字(1)按位与计数法
思路:将二进制1逐次左移,并按位与原数,如原数二进制位该位为0,则得到的值为0,如原数二进制该位为1,则得到的值为1。由此可作计数标准。
#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次。
Way3:按位与减一计数法:
思路:将该数与按位与该数减一,实现从右往左去掉一个1,然后用新数重复此操作。有多少个1则执行多少次循环。
#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;
}
优点:循环次数最佳。
缺点:不太容易想到。
2.2.按位或(|)
规则:两个二进制数同一位为0,进行按位或操作后同位得到0,其余情况均得到1。(类似与逻辑中的或)
引申:
a.按位或可以实现二进制位的随意改变(0->1/1->0)。
2.3.按位异或(^)
规则:两个二进制数同一位相同则同位得到0,相异则同位得1。
推论:
a.按位异或满足交换律。
b.一个数按位异或自己得到0(相同的两个数进行按位异或操作得到0,这是判断两个数是否相同的办法).按位异或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;
}
2.4.按位取反(~)
规则:每一位0变1,1变0。(看起来挺简单)
3.原码反码补码:
原码:按照十进制数直接转化为(写出来)的二进制数。
反码:符号位(第一位/最高位)不变,其他为位按位取反。
补码:反码+1.
正数(无符号数)三码相同。
整形数在内存中存的是补码。
补码取反加一也能得到原码。
进行计算和操作的对象是补码。
用printf()打印出来的是原码。