位运算符以及他们的用途
位运算符以及他们的用途
- C语言中的6个位运算符
- 位运算的实用
一.位运算符
1.& ——按位与运算
"&"是双目运算符(双目运算符就是有两个操作数),
只有当二进制对应位上都是1的时候结果才为1。
a | b | a&b |
---|---|---|
1 | 1 | 1 |
1 | 0 | 0 |
0 | 1 | 0 |
0 | 0 | 0 |
2.| ——按位或运算
“|”是双目运算符,
只有当二进制对应位上有一个为1,结果为1
a | b | a或b |
---|---|---|
1 | 1 | 1 |
1 | 0 | 1 |
0 | 1 | 1 |
0 | 0 | 0 |
3.^ ——按位异或运算
“^”是双目运算符,
只有当二进制对应位上二者不同时,结果为1
a | b | a^b |
---|---|---|
1 | 1 | 0 |
1 | 0 | 1 |
0 | 1 | 1 |
0 | 0 | 0 |
4.~ ——求反运算符
“~”为单目运算符(只有一个操作数),具有右结合性(从右向左执行计算),
a | ~a |
---|---|
0 | 1 |
1 | 0 |
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));