C语言提供了六种位运算符: & 按位与,| 按位或,^ 按位异或,~ 取反,<< 左移,>> 右移。下面让我们来一一了解。这次就精炼一点,侧重于用法,不过多的去关注一些花里胡哨的东西了。
位运算运算规则:
a | b | a&b | a|b | a^b | ~a | a<<b | a>>b |
0 | 0 | 0 | 0 | 0 | 1 | a二进制形式左 | a二进制形式右 |
0 | 1 | 0 | 1 | 1 | 1 | 移b位 | 移b位 |
1 | 0 | 0 | 1 | 1 | 0 | 相当于a乘 2的b | 相当于a除以 2的b |
1 | 1 | 1 | 1 | 0 | 0 | 次方 | 次方 |
一,&按位与运算
按位与是双位运算符,只有对应的两个二进制都为1时,结果为才为1,否则为0。参与运算的数以补码的方式出现。
用法:
1,消除尾一
我第一次见到这种用法是在一个蓝桥杯的题里,要求把一个二进制数最右边的连续的1全部变成0,如果最后一位是0,则原数字保持不变。
输入:
00000000000000000000000001100111
输出:
0000000000000000000000001100000
这道选择题的答案是 x=x&(x+1) 。为了便于学习,我把整段代码也放在这。
#include<iostream>
using namespace std;
void f(int x)
{
for (int i = 0; i < 32; i++) {
printf("%d", (x >> (31 - i)) & 1); //将十进制转化成二进制输出
}
printf(" ");
x = x & (x + 1); //将尾部连续的1消掉
for (int i = 0; i < 32; i++) {
printf("%d", (x >> (31 - i)) & 1);
}
printf("\n");
}
int main() {
f(103);
f(12);
return 0;
}
2,判断奇偶
学过一个星期计算机的应该都知道,判断奇偶我们可以用取余运算符,但这时一个装逼的机会来了,我们可以回归计算机的底层,用&运算符来判断,来看代码。
#include<iostream>
using namespace std;
void check(int x)
{
if (x & 1 == 1) { //按位与运算符判断奇偶
cout << x << "是奇数" << endl;
}
else {
cout << x << "是偶数" << endl;
}
}
int main() {
check(103);
check(12);
return 0;
}
二,| 按位或运算符
对应的二进位有一个位1时,结果位就为1。参与运算的数以补码的方式出现。
举例:
00001001
| 00000101
---------------------
00001101 即9|5=13。
这个运算符不常用,大家知道怎么运算就行,有兴趣的话可以查下资料。
三,^异或运算符
对应的二进位不相等时,结果为1,相等时,结果为0。
用法:
交换两个数
这个作用比较大,因为用&运算符进行交换时,可以避免另外开辟空间来存储临时变量,这样也可以加快程序的速度,在算法上是比较提倡的。来看代码,里面写有详细注释。
#include<iostream>
using namespace std;
int main() {
int a = 12, b = 56;
a = a ^ b;
b = a ^ b; //此时开始交换,将上式代入,相当于 b=a^b^b
//两个相同的数异或之后等于0,任何数与0异或等于其本身
//即b^b=0 , a^0 =a ,此时a赋值给b
a = a ^ b; //将上一个式子代入 a=a^a^b
//a^a=0 , 0^b=b , 此时b的值赋给a
cout << a <<" " << b << endl;
return 0;
}
四,~求反运算符
求反运算符~为单目运算符,具有有结合性。其功能是对参与运算的数的各二进制位按位求反。
例如,~9的运算为~(0000000000001001),结果为 1111111111110110。
五,<<左移运算符
左移运算符是双目运算符,其功能是把“<<”左边的运算数的各二进位全部左移若干位,由运算符右边的数指定移动的位数,高位丢弃,低位补0。
用法:
在数字没有溢出的前提下,对于正数和负数,左移一位相当于乘以2的1次,左移n位相当于乘以2的n次方。
左移运算比乘法快,可以用来优化代码。
六,>>右移运算符
右移运算符是双目运算符,其功能是把运算符左边的运算数的各二进位全部右移若干位,运算符右边的数指定右移的位数。
对于有符号的数,在右移时,符号位将随之移动。当为正数时,最高位补0,为负数时,符号位为1,最高位补1或是补0取决于编译系统的规定,大多数系统规定补1。
用法:
和左移运算差不多,不过,右移一位表示除以2的一次方,右移n位表示除以2的n次方
同样可以用来优化代码
目前我只总结了这些,随着算法学习的深入,之后应该会接触到更多的,到时候我会再进行补充。