文章目录提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
- 前言
- 一、位运算符表格
- 二、位运算符详解
- 三.位运算符的一些应用
- 1.确定某个操作数的二进制补码中的最低位
- 2.确定某个操作数二进制补码中1的个数
- 3.交换两个数
- 4.输出操作数二进制补码中的奇数位和偶数位
- 总结
前言
C语言中提供了6中基本位运算符。位运算是对每个二进制位分别进行操作;位运算符的操作对象只能是整型或字符型数据,不能为实数型数据(C语言中,实数型数据只能用十进制表示,当然不能进行位运算)。
一、位运算符表格
| 运算符 | 名称 | 实例 | 结果 |
|---|---|---|---|
| ~ | 换位取反 | ~1010 | 0101 |
| & | 换位与 | 0110&1010 | 0010 |
| | | 按位或 | 0110|1010 | 1110 |
| ^ | 按位异或 | 0110^1010 | 1100 |
| << | 按位左移 | 01101010<<2 | 10101000 |
| >> | 按位右移 | 01101010>>2 | 00011010 |
1.按位取反 ~
规则:将操作对象的二进制补码中的每一位安危取反,即1变0,0变1。
举例:
~101010011
——————————————————
010101100
—————————————————————————————————
2.按位与 &
规则:两个操作数二进制补码的每一个对应位都为1时结果为1,其他情况时为0。(即只要有一个为0结果就为0)
举例:
11000011
&10100110
——————————————————————
10000010
- 按位或 |
规则:两个操作数二进制补码的每一个对应位都为0时结果为0,其他情况时为1。(即只要有一个为1结果就为1)
举例:
11000011
&10100110
——————————————————————
11100111
4.按位异或 ^
规则:两个操作数二进制补码的每一个对应位不同时结果为1,相同时为0。(异或异或着重点在异)
举例:
11000011
&10100110
——————————————————————
01100101
5.按位左移 <<
规则:将操作数的二进制补码向左移动指定的位数,并且将高位舍弃,在低位补0。(左移即将最左边的n位舍弃,在最右边补n个0)
1 0 1 0 0 1 1 0<<2
_____________________
1 0 0 1 1 0 0 0
左移n位相当于该数乘以2n,前提是该数在舍弃的高位中不包含1的情况。
6.按位右移 >>
规则:将操作数的二进制补码向右移动指定的位数,并且将低位舍弃,在高位补0。(右移对于无符号数而言:即将最右边的n位舍弃,在最左边补n个0)
1 0 1 0 0 1 1 0>>2
_____________________
0 0 1 0 1 0 0 1
三.位运算符的一些应用
1.确定某个操作数的二进制补码中的最低位
方法:
-
将这个操作数与1进行&操作
原理:1&1=1 0&1=0
即不论是1还是0,与1进行&操作后都能得到原来的值,进而可以确认。
2. 将这个操作数与0进行|操作
原理:
1|0=1
0|0=0
即不论是1还是0,与0进行 | 操作后都能得到原来的值,进而可以确认。
2.确定某个操作数二进制补码中1的个数1.第一种:结合&操作符和>>操作符。
解释:因为操作数的二进制数补码中的最低位与1进行&操作后就能知道这个最低位是1还是0,故只要将操作数右移,然后操作数和1进行与操作,结果为1就说明最低位为1,计数器加1,结果为0则不会进入if条件语句。操作数的二进制数补码一共有32位,所以用for循环进行32次重复操作。
#includeint main() { int num; printf("请输入一个十进制整数:"); scanf("%d", &num); int ret = 0; int i = 0; for (i = 0; i < 32; i++) { if (((num >> i) & 1) == 1) { ret++; } } printf("%d的二进制补码中1的个数=%d", num, ret); return 0; }
2.第二种:应用 & 操作符
原理:num=num&(num-1)可使得重新得到的num的二进制补码减掉一个1
假设输入一个整数15,其二进制补码为1111
1. num ——>1111
(num-1) ——>1110
1 1 1 1
&1 1 1 0
_______________
1 1 1 0
2. num ——>1110
(num-1) ——>1101
1 1 1 0
&1 1 0 1
_______________
1 1 0 0
3. num ——>1100
(num-1) ——>1011
1 1 0 0
&1 0 1 1
_______________
1 0 0 0
4. num ——>1000
(num-1) ——>0111
1 0 0 0
&0 1 1 1
_______________
0 0 0 0
#include3.交换两个数int main() { int num; printf("请输入一个十进制整数:"); scanf("%d", &num); int count = 0; while (num) { num = num & (num - 1); count++; } printf("%d的二进制补码中1的个数=%d", num, count); return 0; }
说明:这个方法比较适用于不允许创建临时变量的交换题目
原理:
a^a=0
a^0=a
解释:b=a^b 等价于 b=a^b^b。因为b^b=0,则b=a^0=a;
同理a=a^b等价于a=a^b^a。因为a^a=0,则a=0^b=b。
故交换成功。
#include4.输出操作数二进制补码中的奇数位和偶数位int main() { int a = 10; int b = 20; printf("交换前a=%d,b=%dn", a, b); a = a ^ b; b = a ^ b; a = a ^ b; printf("交换后a=%d,b=%dn", a, b); return 0; }
说明:
例如要取出0100 0001 1010的第7位(从低向高数),就可以使用右移操作符将操作数右移6位后和1进行与操作。
同理取出操作数二进制补码的奇数位和偶数位其实就是循环进行左右移操作然后与1操作。
#include总结int main() { int num; printf("请输入一个十进制整数:"); scanf("%d", &num); //获取偶数位 printf("偶数位为:n"); for (int i = 31; i >= 1; i=i-2) { printf("%d ", (num >> i) & 1); } printf("n"); printf("奇数位为:n"); //获取奇数位 for (int j = 30; j >= 0; j = j - 2) { printf("%d ", (num >> j) & 1); } return 0; }
适当的使用位运算符有时候会使得代码变得简洁,但需要注意以下:
- 位运算符操作对象的数据类型只能是整型或字符型。
- 位运算符必须对操作数的所有二进制进行位运算,不允许对其中的某一位进行操作。



