C语言中的位操作符总结

C语言中基本的位操作符有 左移、右移、按位与、按位或、按位异或、取反)
我们用表格先归总一下

名称 符号 运算规则
左移 << 高位丢弃,低位补0
右移 >> 对无符号数,高位补0. 对有符号数,算数右移高位补符号位,逻辑右移高位补0
按位与 & 两位同为“1”,结果才为“1”,否则为0
按位或 l 两位只要有一个“1”,结果就为“1”,否则为0
按位异或 ^ 两位 同“0”异“1”
取反 ~ “1”变“0”,“0”变“1”

下面来结合代码说明

**1.左移 << **

	int num = 10;    
	num = num << 1;  
	printf("%d",num);

C语言中的位操作符总结_第1张图片
所以左移几位就是原数乘2的n次方
**2.右移 >> **
右移运算分两种(因为数在内存中以补码形式存储的):

  1. 逻辑右移不考虑符号位,高位补0,低位溢出的丢弃
  2. 算术右移考虑符号位,高位用原该值的符号位填充,低位溢出的丢弃
	int num1 = 10;      //二进制    00000000 00000000 00000000 00001010
	num1 = num1 >> 1;   //右移1位   00000000 00000000 00000000 00000101

	int num2 = -10;     //二进制    11111111 11111111 11111111 11110110
	num2 = num2 >> 1;   //右移1位   11111111 11111111 11111111 11111011 
	printf("%d   %d\n", num1,num2); //num1 = 5 ,num2 = -5

ps:对于移位运算符,不要移动负数位,这个是标准未定义的
例:

int num = 10;
num>>-1;//error

**3.按位与 & **
参加运算的两个数,按二进制位进行“与”运算:
0&0=0; 0&1=0; 1&0=0; 1&1=1;
例:

	int num1 = 1; //二进制 0001
	int num2 = 2; //二进制 0010
	int num = num1 & num2; //按位与运算 0000
	printf("%d\n", num);  //num = 0

**4.按位或 | **
参加运算的两个数,按二进制位进行“或”运算:
0|0=0; 0|1=1; 1|0=1; 1|1=1;
例:

	int num1 = 1; //二进制 0001
	int num2 = 2; //二进制 0010
	int num = num1 | num2; //按位或运算 0011
	printf("%d\n", num); //num = 3

**5.按位异或 ^ **
参加运算的两个数,按二进制位进行“异或”运算:
0^0=0; 0^1=1; 1^0=1; 1^1=0;
按位异或有几个重要性质:
例:
1、交换律 a ^ b = b ^ a
2、结合律 (a^b) ^ c = a^ (b^c)
3、对于任何数x,都有x ^ x = 0 ,x ^ 0 = x

	int num1 = 1; //二进制 0001
	int num2 = 2; //二进制 0010
	int num = num1 ^ num2; //按位异或运算 0011
	printf("%d\n", num); //num = 3

ps:以上三个位操作符(按位与、按位或、按位异或)的操作数必须是整数
**6.取反 ~ **
对一个数的二进制按位取反:1变0,0变1

	int num = 1; //二进制 00000000 00000000 00000000 00000001
	num = ~num;  //二进制 11111111 11111111 11111111 11111110
	printf("%d\n", num); //取反运算 num = -2

下面来看几道题,运用位运算实战一下

1.不创建临时变量(第三个变量),实现两个数的交换(一道面试题)

#include 
int main()
{
	int a = 1;  //0001
	int b = 2;  //0010
	a = a^b;	//0001 ^ 0010 = 0011
	b = a^b;	//0011 ^ 0010 = 0001
	a = a^b;	//0011 ^ 0001 = 0010
	printf("a = %d b = %d\n", a, b); //a = 2 b = 1
	return 0;
}

理解的时可以参照上面列出的按位异或的几个性质
2. 求一个整数存储在内存中的二进制中1的个数

#include
int main()
{
	int num = -1;
	int i = 0;
	int count = 0;//计数
	for(i=0; i<32; i++)
	{
		if( ((num>>i)&1) == 1 )
		count++;
	}
	printf("二进制中1的个数 = %d\n",count);
	return 0;
}

思考一下还有没有更简洁的做法?(上面这种做法必须要循环32次)

#include 
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;
}

3.给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素(leetcode 136)

class Solution {
public:
   	 int singleNumber(vector<int>& nums) {
     int val = 0;
     for(auto e : nums)
     {
         val ^= e;
     }
     return val;
    }
};

你可能感兴趣的:(C语言拾遗)