位运算


位运算是指按二进制进行的运算,直接操作二进制的位,操作效率较高。在系统软件中,常常需要处理二进制位的问题。C语言提供了6个位操作运算符。这些运算符只能用于整型操作数,即只能用于带符号或无符号的char,short,int与long类型。

1.位运算符与 &

& 按位与,对应的两个二进制位均为1时,结果才为1,否则为0

9 & 5 = 1
9 对应二进制 --> 1001
5 对应二进制 --> 0101

 1001
&0101
----------
0001   // 转为十进制为1

2.位运算符或 |

| 按位或,对应的两个二进制位有一个位1,结果就为1,否则为0

9 | 5 = 13
9 对应二进制 --> 1001
5 对应二进制 --> 0101

 1001
|0101
----------
1101   // 转为十进制为13

3.位运算符异或

^按位异或,对应的两个二进制位不相同时,结果为1,否则为0

9 ^ 5 = 12
9 对应二进制 --> 1001
5 对应二进制 --> 0101

 1001
^0101
----------
1100   // 转为十进制为12

4.位运算符取反

~取反,对于二进制位取反(0变1,1变0)

~9 = -10
~5 = -8

9 对应二进制补码 --> 0000 0000 0000 0000 0000 0000 0000 1001
先将补码取反
~0000 0000 0000 0000 0000 0000 0000 1001
------------------------------------------------------------------
 1111 1111 1111 1111 1111 1111 1111 0110		// 得到取反后的补码
 然后将补码转为反码,由于二进制首位是1,表示为负数,则需要先转为反码(在补码的基础上减1)
 1111 1111 1111 1111 1111 1111 1111 0101		// 得到反码
 然后将反码转为原码(除二进制首位外,其余位数取反)
 1000 0000 0000 0000 0000 0000 0000 1010	// 得到原码,转换为十进制为 -10
 


5 对应二进制补码 --> 0000 0000 0000 0000 0000 0000 0000 0101
先将补码取反
~0000 0000 0000 0000 0000 0000 0000 0101
------------------------------------------------------------------
 1111 1111 1111 1111 1111 1111 1111 1010		// 得到取反后的补码
 然后将补码转为反码,由于二进制首位是1,表示为负数,则需要先转为反码(在补码的基础上减1)
 1111 1111 1111 1111 1111 1111 1111 1001		// 得到反码
 然后将反码转为原码(除二进制首位外,其余位数取反)
 1000 0000 0000 0000 0000 0000 0000 0110	// 得到原码,转换为十进制为 -8

5.位运算左移右移

左移

把整数a的各二进制位全部向左移动n位,高位丢弃,低位补0,左移n位其实就是乘以2的n次方

  • 由于左移是丢弃最高位,0补最低位,所以符号位也会被丢弃,左移出来的结果值可能会改变正负性

正数左移

2 << 1;		// 4
2的二进制表现形式:0000 0000 0000 0000 0000 0000 0000 0010
整体向左移动:     0000 0000 0000 0000 0000 0000 0000 0100		--> 4

负数左移

-2 << 1;	// 4
-2的二进制表现形式:1000 0000 0000 0000 0000 0000 0000 0010
整体向左移动:      0000 0000 0000 0000 0000 0000 0000 0100		--> 4
注意:负数二进制首位的标志符被顶出去丢弃掉了
右移

把正数a的各二进制位全部向右移n位,保持符号位不变。右移n位其实就是除以2的n次方

  • 为正数时,符号位为0,最高位补0
  • 为负数时,符号位为1,最高位补1,使用补码进行移动

正数右移

2 >> 1;		// 1
2的二进制表现形式:0000 0000 0000 0000 0000 0000 0000 0010
整体向左移动:     0000 0000 0000 0000 0000 0000 0000 0001		--> 1

负数右移

-2 >> 1;	//
-2的二进制表现形式:1000 0000 0000 0000 0000 0000 0000 0010
先转换成反码:      1111 1111 1111 1111 1111 1111 1111 1101
再转换成补码:      1111 1111 1111 1111 1111 1111 1111 1110		// 反码的基础上+1
补码向右移动:      1111 1111 1111 1111 1111 1111 1111 1111		// 首位不动,向右移动,缺位补1
补码转成反码:      1111 1111 1111 1111 1111 1111 1111 1110		// 补码-1
反码转成原码:      1000 0000 0000 0000 0000 0000 0000 0001		// 转成十进制为 -1
左移右移应用场景
  • 某个数乘以2的n次幂,使用左移n
  • 某个数除以2的n次幂,使用右移n

6.练习

6.1 位运算判断奇偶数
#include <stdio.h>
int main(int argc, const char * argv[]) {
    /*
     分析:
     1的二进制 --> 0000 0000 0000 0000 0000 0000 0000 0001
     2的二进制 --> 0000 0000 0000 0000 0000 0000 0000 0010
     3的二进制 --> 0000 0000 0000 0000 0000 0000 0000 0011
     4的二进制 --> 0000 0000 0000 0000 0000 0000 0000 0100
     5的二进制 --> 0000 0000 0000 0000 0000 0000 0000 0101
     6的二进制 --> 0000 0000 0000 0000 0000 0000 0000 0110
     7的二进制 --> 0000 0000 0000 0000 0000 0000 0000 0111
     8的二进制 --> 0000 0000 0000 0000 0000 0000 0000 1000
     总结出规律:奇数二进制最后一位为1,偶数二进制最后一位为0
     */
    int n = 10;
    if (n & 1) {
        printf("奇数\n");
    } else {
        printf("偶数\n");
    }
    return 0;
}
6.2 位运算进行2个变量数据交换
#include <stdio.h>

int main(int argc, const char * argv[]) {
    int a = 456456;
    int b = 1045646;
    printf("换位前: a --> %i  b --> %i\n", a, b);
    a = a ^ b;
    b = a ^ b;
    a = a ^ b;
    printf("换位后: a --> %i  b --> %i\n", a, b);
    
    return 0;
}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值