C language bitwise operator & | ^ ~

1. & Bitwise AND

(1) Introduction

& - 按位与

int a = 5,b = -6;

a & b - 二者需要使用补码来进行运算

0000 0000 0000 0000 0000 0000 0000 0101 - 5的补码

1111 1111 1111 1111 1111 1111 1111 1010 - -6的补码

0000 0000 0000 0000 0000 0000 0000 0000 -  5 & -6 的结果

& - 在一一对应的二进制位上,只有同时为1的二进制位运算的结果才是1 反之其他皆为0

(2), application

例如:

int a = 21 ;

0000 0000 0000 0000 0000 0000 0001 0101 - 21的补码
                                 第五的位数

现在,需要我们判断 21 的二进制位数 的第五个位数是1还是0 

此时,若要解决该问题,我们可以利用 & 的性质解决问题

首先我们先将第五位数移到最右边,我们使用 >> 操作符 得到一串新的二进制数位

0000 0000 0000 0000 0000 0000 0000 0001 - a>>4

随后使用 (a>>4)&1 进行运算,最后进行对比 

0000 0000 0000 0000 0000 0000 0000 0001 - 1的补码

0000 0000 0000 0000 0000 0000 0000 0001 - a>>4

0000 0000 0000 0000 0000 0000 0000 0001 - (a>>4)&1的结果 

通过 & 的特性,我们得知了21的二进制位数的第五个位数是1

Second, | bitwise or

介绍:

| 按位或

int a = 5, b = -6;

a | b -二者需要使用补码进行运算


0000 0000 0000 0000 0000 0000 0000 0101 - 5的补码

1111 1111 1111 1111 1111 1111 1111 1010 - -6的补码

1111 1111 1111 1111 1111 1111 1111 1111 -  5 | -6的结果

| - 在一一对应的二进制位上,只要有1时就为1,只有同时为0时才能为0

(2), application

例如:

int a = 13;

// 0000 0000 0000 0000 0000 0000 0000 1101 - 13的补码
                              要求将13的二进制位数中的第五位改成1 

// 现在,要求将13的二进制位数中的第五位改成 1  

// 对于此问题,我们可以使用 | 的性质解决问题 

// 首先,我们先展示出 1 的二进制位数

// 0000 0000 0000 0000 0000 0000 0000 0001 - 1的补码

// 其次,我们使用 1 << 4 将1的二进制位数中唯一的1进行移动到二进制数位的第5位

// 随后,在使用 | 解决问题

// 0000 0000 0000 0000 0000 0000 0000 1101 - 13的补码

// 0000 0000 0000 0000 0000 0000 0001 0000 - 1<<4的结果

// 通过 | 的性质,我们可以得到

// 0000 0000 0000 0000 0000 0000 0001 1101

3. ^ Bitwise XOR

(1) Introduction

^ - 按位异或

int a = 5,b = -6;

a ^ b - 二者需要使用补码来进行运算

0000 0000 0000 0000 0000 0000 0000 0101 - 5的补码

1111 1111 1111 1111 1111 1111 1111 1010 - -6的补码

1111 1111 1111 1111 1111 1111 1111 1111 -  5 ^ -6 的结果

^ - 在一一对应的二进制位上,相同的位数为0,不相同的位数为1

(2), application

例如:

应用一:

int a = 3 , b = 5;

求不允许创建临时变量,使用按位异或操作符,交换两个整数的内容 

首先,我们要知道 ^ 有一个特点,那就是 a ^ a = 0 以及 a ^ 0 = a 

所以题目的要求可以使用以下代码解决:

 a = a ^ b; - a = 3^5

 b = a ^ b; - b = a ^ b ^ b = 3 ^ 5 ^ 5 = 3 ^ 0 = 3 - b = 3
                    
 a = a ^ b; - a = a ^ b = 3 ^ 5 ^ 3 = 3 ^ 3 ^ 5 = 0 ^ 5 = 5 - a = 5 

通过以上的运算,我们又得知 ^ 和数学符号 乘号× 一样 具有交换律的特点

应用二:

给你一个 非空 整数数组 nums ,除了某个元素只出现一次以外,其余每个元素均出现两次。请实现函数:
int singleNumber(int nums[], int numsSize),找出那个只出现一次的元素。

int singleNumber(int nums[], int numsSize)
{
	int k = 0;
	int i = 0;
	for (i = 0; i < numsSize; i++)
	{
		k = k ^ nums[i];
      //0^4^1^2^1^2 = 0^4^0^0 = 0^4 = 4 利用了^的特性,也就是 a ^ a = 0 和 0 ^ a = a
	}
	return k;
}


int main()
{
	int nums[] = { 4,1,2,1,2 };
	int numsSize = sizeof(nums) / sizeof(nums[0]);
	int ret = singleNumber(nums,numsSize);
	printf("%d",ret);
	return 0;
}



注意,这种异或操作是有局限性:
1.只能作用于整数交换
2.代码的可读性差
3.代码执行的效率也是低于使用第3个变量的方法

Four, ~ bitwise inversion

(1) Introduction

~ - 按位取反

int a = 0;

~ a  - 需要使用补码来进行运算

0000 0000 0000 0000 0000 0000 0000 0000 - 0的补码


1111 1111 1111 1111 1111 1111 1111 1111 - ~0 的结果


~ - 在二进制数位上是0的变成1,是1的变成0,且包括了符号位

(2), application

例如:

int a = 29;

// 0000 0000 0000 0000 0000 0000 0001 1101 - 29的补码
                                 要求第五位数改成0

// 现在,要求将29的二进制位数中的第五位改成 0  

// 对于此问题,我们可以使用 ~ 的性质解决问题 

// 首先,我们先展示出 1 的二进制位数

// 0000 0000 0000 0000 0000 0000 0000 0001 - 1的补码

// 其次,我们使用 1 << 4 将1的二进制位数中唯一的1进行移动到二进制数位的第5位

// 0000 0000 0000 0000 0000 0000 0001 0000 - 1<<4的结果

// 随后,在使用 ~ 进行取反

// 1111 1111 1111 1111 1111 1111 1110 1111 - ~(1<<4)的结果

// 再之后,使用 & 的性质解决问题

// 0000 0000 0000 0000 0000 0000 0000 1101 - a & ~(1<<4)的结果


Guess you like

Origin blog.csdn.net/2301_76445610/article/details/132133124