位运算符以及他们的用途

位运算符以及他们的用途

  1. C语言中的6个位运算符
  2. 位运算的实用

一.位运算符

1.& ——按位与运算

"&"是双目运算符(双目运算符就是有两个操作数),
只有当二进制对应位上都是1的时候结果才为1。

aba&b
111
100
010
000

2.| ——按位或运算

“|”是双目运算符,
只有当二进制对应位上有一个为1,结果为1

aba或b
111
101
011
000

3.^ ——按位异或运算

“^”是双目运算符,
只有当二进制对应位上二者不同时,结果为1

aba^b
110
101
011
000

4.~ ——求反运算符

“~”为单目运算符(只有一个操作数),具有右结合性(从右向左执行计算),

a~a
01
10

5.<< ——左移运算符

“<<”是双目运算符,将二进制位进行左移操作,
左移n位就是乘以2的n次方。

“<<”左边的运算数的各二进位全部左移若干位,由“<<”右边的数指定移动的位数,高位丢弃,低位补0。

6.>> ——右移运算符

“>>”是双目运算符,将二进制位进行右移操作,
右移n位就是除以2的n次方。

“>>”左边的运算数的各二进位全部右移若干位,“>>”右边的数指定移动的位数。同时注意,>>运算符是用符号位来填充高位的。

二.位运算符的实用

位运算符是针对二进制位上的运算

1.判断奇偶数

因为在二进制中只有当最后一位二进制数为1的时候才表示奇数,而相反只有当最后一位二进制数为0的时候才表示偶数,所以利用“&”的特点,我们可以得到:

if((x&1) == 1)
	printf("x是奇数\n");
	
else if((x&1) == 0)
	printf("x是偶数\n");

2.交换两个整数

在C语言中,我们可以编写一个swap函数来交换两个整数:

void sswap(int *a,int *b)
{
	int t;
	t = *a;
	*a = *b;
	*b = t;
}

但是其实也可以使用“^”的特性来进行两个整数的交换:

void sswap(int *a,int *b)
{
	*a = *a ^ *b;
	*b = *b ^ *a;
	*a = *a ^ *b;
}

3.用位运算符求整数的绝对值

正数的补码,反码与原码相同;负数的补码等于原码的反码+1。

补码:
正整数的补码是其二进制表示,与原码相同;
例如:7的补码是00000111。

负数的补码是将其原码除符号位外的所有位取反(0变1,1变0,符号位为1不变)后加1。
例如:-7:7(00000111)——> 所有位取反(11111000) ——>加1(11111001)。

0的补码是:00000000。

反码:
顾名思义就是在原码的基础上取反,0取1,1取0。

所以求一个整数的绝对值如下所示:

int ffabs(int x)
{
	if(x>0)
		return x;
	else
		return ~x + 1;
}

4.异或“^”的一个作用

对于一个整数而言:
异或0为他本身,异或-1为取反(因为-1的二进制位上全是1),异或自己为0;

a ^ 0 = a;
a ^ -1 =-a;
a ^ a = 0;

这样的话我们就能通过异或来找出成对出现的数中落单的那一个,或者是单个出现的数中成对的那一个。

5.判断一个正整数是否为2的整数次方

在二进制上面,只存在一个二进制位上是1的时候才是2的整数次方,所以也可以转化为求二进制位上是否只有一个1,其余全是0;

if((n - 1) & n) == 0)
	printf("yes\n");
else
	printf("no\n");

6.将整数的奇偶位互换

int ji = n & 0x55555555;
	//与01010101做与运算,取出奇数位
int ou = n & 0xaaaaaaaa;
	//与10101010做与运算,取出偶数位
int new = ((ou>>1)^(ji<<1));