- 首页>
- C语言中的位运算
C语言中的位运算
妹妹最近要考计算机二级了,选的C,今天问到我关于位运算的问题,给她解答完之后,发现位运算其实有很多可玩的地方,故把C语言中位运算的基础知识整理成此文。
一、运算符
运算符 | 定义 |
---|---|
& | “与”,除了1 & 1 = 1,其余均为0 |
“或”,除了0 0 = 0,其余均为1 | |
~ | “非”,取反,^ 1 = 0,^ 0 = 1 |
^ | “异或”,若异或的两数不同则结果为1,否则为0。(同0异1) |
<< | “左移”,将二进制数向左移n位,后面用0补全。如:1001 << 2 = 100100 |
>> | “右移”,将二进制数向右移n位,也可以理解为删除后面的n位。如:1001 >> 2 = 10 |
二、位运算的实际运用
1. & 运算
`&`运算可以用来判断数的奇偶。比如,十进制的4,转换成二进制就是`100`,这时,我们可以用`100` & 1,即`100` & `001`,结果为0(二进制的运算是从左到右,逐位运算,右边对齐,空位补零),可知该数为偶数;十进制的5,转换成二进制就是`101`,`101` &`001`=1,可知该数为奇数。
PS:这是因为二进制转换为十进制时,是每一位的数(0或1)乘以2的n-1次方(n为该数所在的位数,如二进制数100转换为十进制:
1*2^2 + 0*2^1 + 0*2^0 = 4 +0 +0 = 4。当二进制数
100
和1进行&运算时,由于1(001
)前面都为0,所以结果只和最后一位有关系,最后一位为0,则&1结果为0,反之则为1。从上面二进制转十进制的过程可以看到,前面都是2*n相加,为偶数,最后一位是n*2^0=n,所以结果是奇是偶只和最后一位是1还是0有关。)
2. | 运算
`|`运算可以用来把一个二进制数的最后一位变成1。比如,十进制数5,转换为二进制就是`101`,这时,我们可以用`101` | 1(即`101` | `001`),按照二进制位运算的规则:从左到右,逐位运算,右边对齐,空位补零,这个式子的结果应该为`101`,最后一位为1;同理,十进制数4,转换为二进制就是`100`,`100` | 1(即`100` | `001`)的结果为`101`,最后一位同样为1。
PS:我们可以利用这个方法取到不大于某数的最大偶数。假设有数
N
,(N
| 1 ) - 1的结果就是不大于N
的最大偶数,例如有十进制数5,则( 5 | 1 ) - 1 = 4( (101
|001
) - 1 =100
)。
3. ~ 运算
`~` 运算比较简单,对二进制数逐位取反就可以了,如十进制数4(`100`),对其进行`~`运算,即~4
( ~ 100
),结果为011
,即十进制数3。
4. ^ 运算
`^`运算可以用来交换两个变量的数和进行简单的数据加密。
`^`运算有一个特点,即`^`运算的逆运算是`^`本身。举个例子,我们把十进制数4(`100`)和十进制数5(`101`)进行`^`运算,即4 ^ 5( `100` ^ `101` = `001` ),结果为十进制数1;我们再把十进制数4(`100`)和十进制数1(`001`)进行`^`运算,即4 ^ 1( `100` ^ `001` = `101` ),结果为十进制数5。从这个例子我们就可以验证`^`运算的逆运算是`^`本身这一特点。
根据`^`的逆运算是其本身这一特性,我们可以进行交换变量数据的操作,先贴代码:
#include
//利用^运算交换两个变量
int main(){
int a = 4;
int b = 5;
printf("Before exchange: a = %d, b = %d.\n", a, b);
a = a ^ b;
b = a ^ b;
a = a ^ b;
printf("After exchange: a = %d, b = %d.\n", a, b);
return 0;
}
程序运行结果为:
Before exchange: a = 4, b = 5.
After exchange: a = 5, b = 4.
假设你要把你的手机号在群里告诉你的小伙伴,同时不想让别人知道,那么你可以把你的手机号码和某个你俩都知道的数进行`^`操作(比如你的生日blablabla),你的小伙伴在收到你的信息后,可以用收到的数和你的生日进行`^`操作,最终结果就是你的手机号码。
5. << 运算
`<<`运算可以将m向左移动n位(后面补0)。请大家思考,如果我们计算`5 << 4`这个表达式,它的结果会如何呢?根据`<<`运算的定义,将5(`101`)像左移动4位并在末尾补0,其结果为`1010000`,即十进制数80,80其实就是`5 * ( 2 ^ 4 )`的计算结果,大家还可以自己找几个数来试试。不难看出,`m << n`的结果即为`m*2^n`,代码如下:
#include
#include
//比较5*2^4和5<<4的计算结果
int main(){
int shl_result = 5 << 4;
double pow_result = 5 * pow(2, 4);
printf("5 * 2 ^ 4 = %lf\n", pow_result);
printf("5 << 4 = %d\n", shl_result);
return 0;
}
程序运行结果为:
5 * 2 ^ 4 = 80.000000
5 << 4 = 80
6. >> 运算
`>>`运算可以将m向右移动n位(后n位直接去掉)。类似`<> 4`的结果是多少呢?根据`>>`运算的定义,将160(`10100000`)向右移动4位(去掉末尾4个0),其结果为`1010`,即十进制数10,10其实就是`160 / (2 ^ 4)`的结果,大家也可以另外找几个数来验证。通过观察不难看出,`m >> n`的结果即为`m /2^n `,代码如下:
#include
#include
//比较160/2^4和160>>4的计算结果
int main(){
int shr_result = 160 >> 4;
double pow_result = 160 / pow(2, 4);
printf("160 / 2 ^ 4 = %lf\n", pow_result);
printf("160 << 4 = %d\n", shr_result);
return 0;
}
程序运行结果为:
160 / 2 ^ 4 = 10.000000
160 << 4 = 10
PS:关于
<<
和>>
两种移位运算为什么会导致结果等于m*2^n
或m/2^n
,大家可以观察二进制转换为十进制的计算方法,很容易就能明白。
尾巴
关于C语言中的位运算符的基础知识暂时就讲到这里,其实位运算符在很多场景下可以帮助我们优化程序的运行效率,比如我们可以使用`m >> 1`来代替需要`m / 2`的场景,这样可以使得程序的运行效率大大提高,比如二分查找、堆的插入操作等等。欢迎大家在评论区留言哦~
杨耀东 万事都有选择,哪怕是真相也不例外。
为你推荐
- 重庆市仙桃大数据与物联网学院,11月18日,正式启航!
仙桃大数据学院
- 青年人才科技创新交流会暨西南AI联盟成立
仙桃大数据学院
- 招聘丨仙桃大数据与物联网职业培训学院人员招聘简章
仙桃大数据学院
- 共话前沿技术 | 人工智能前沿技术沙龙在我院成功召开
仙桃大数据学院
- 机器学习五大流派
苏幕遮
- 新时代新职业新工种创新试点:重庆市渝北区大数据分析师特色工种
仙桃大数据学院
- 产教融合——腾恩阿尔克科技集团与仙桃大数据学院举行业务合作
仙桃大数据学院
- 仙桃大数据与物联网创新学院
仙桃大数据学院
- 纯干货|先进实用,且听他讲“工业物联网体系架构”
仙桃大数据学院
- 眼部识别三兄弟今天带你认识他们
仙桃大数据学院