目录
前言
一、原码、反码、补码
二、移位操作符
三、位操作符:&、|、^、~
四、经典例题分析:
总结
前言
本文将详细介绍C语言中左移操作符<<,右移操作符>>,按位与&,按位或|,按位异或^,按位取反~这六种有关二进制位运算的操作符,为此本文还会介绍整数的原码、反码、补码,后面还有一些经典例题算法,以此来更好的理解这六种操作符,希望对大家有所帮助
一、原码、反码、补码
(注:因涉及二进制以及进制转换,不了解的需先了解二进制和进制转换)
C语言位操作符的操作数都为整数,准确的说是整数的二进制数,而补码才是一个整数真正存储在内存中的形式,以下的操作符也都是作用在补码上
整数有正负之分:
- 正整数的原、反、补码都相同。
- 负整数的三种表示方法各不相同。
原码:直接将数值按照正负数的形式翻译成二进制得到的就是原码。
反码:将原码的符号位不变,其他位依次按位取反就可以得到反码。
补码:反码+1就得到补码。
我们看下图:
(注:整形占4个字节,一个字节占8个比特位,所用一个整形占32个比特位)
负整数转换规则记忆技巧:
- 原码到补码:取反,+1。
- 补码到原码:也是取反,+1。也可以先-1到反码,再取反到原码,结果是一致的
对于整形来说:数据存放内存中其实存放的是补码。
为什么呢?
在计算机系统中,数值一律用补码来表示和存储。原因在于,使用补码,可以将符号位和数值域统一处理;同时,加法和减法也可以统一处理(CPU只有加法器)此外,补码与原码相互转换,其运算过程是相同的,不需要额外的硬件电路
我们可以验证一下,其实用原码计算是得不到准确结果的,补码计算才能得到准确的结果
二、移位操作符
- << 左移操作符
- >> 右移操作符
注:移位操作符的操作数只能是整数
1.左移操作符 <<
移位规则:左边抛弃、右边补0 (注:是将整数的补码左移)
语法:整数<<移动位数
我们用上面的14和-9举例:
然后我们画图分析:
通过计算分析,结果一致
总之,左移就记住:左边抛弃,右边补0(补码)
2.右移操作符 >>
移位规则:首先右移运算分两种:
1. 逻辑右移:左边用0填充,右边丢弃
2. 算术右移:左边用原该值的符号位填充,右边丢弃
语法:整数>>移动位数
那么,右移操作符有两种规则怎么用,其实,绝大多数编译器使用的是算术右移,所以我们一般也是使用算术右移
还是用14和-9举例
画图分析:
通过计算分析:结果一致,使用的是算术右移
算术右移:左边用原该值的符号位填充,右边丢弃(补码)
三、位操作符:&、|、^、~
注:它们的操作数必须为整数,并且是作用于补码
1.按位与 &
规则:当两个相应的二进制位都是1时,结果位才是1,否则,结果位为0
简述:都为1则为1,否则为0
语法:整数&整数
我们看代码:
继续画图分析:
计算分析与结果一致
所以,&:只有相同位置都为1,才是1,否则就是0
2.按位或 |
规则:如果两个相应的二进制位中至少有一个为1,结果位为1,如果都是0,结果位为0
简述:有1则为1,否则为0
语法:整数 | 整数
我们看代码:
继续画图分析:
计算分析与结果一致
所以,|:相应位有1就是1,否则就是0
3.按位异或 ^
规则:如果两个相应的二进制位不同,则结果位为1,如果相同,则结果位为0
简述:相异为1,相同为0
语法:整数^整数
我们看代码:
继续画图分析:
计算分析与结果一致
所以,^:对应位相异为1,相同为0
4.按位取反 ~
规则:与字面意思一致,把二进制位的每一位1变为0,0变为1
语法:~整数
这个比较简单,并且是单目操作符
但是需要注意的是:符号位也会被取反
看代码:
分析:
计算分析与结果一致
需注意的是符号位也会改变
四、经典例题分析:
1.不创建变量,交换两个整数值
我们平时交换两个整数一般采用创建一个变量,当做中间量来交换两个整数,现在不允许创建一个变量,我们因该怎么做呢?
首先我们需要了解按位异或^的一些计算规律:
假如整形a和b,那么它们满足以下规律:
- a^a=0
- 0^a=a
- a^b^a=b(交换律,即先计算a^a=0,再计算0^b=b)
我们简单验证一 a^a=0:很明显,两个相同的数二进制位肯定相同,按位异或就为0
验证 0^a=a:
验证 a^b^a=b;
规律都验证成功
因此这个代码我们可以这样写:使用交换律
2.计算整数二进制中有多少个1
关于这个问题有多种解法,这里主要介绍"Brian Kernighan算法"即 n&(n-1)
定义一个整数变量n,通过不断将输入数字n与n-1进行按位与&运算,每次运算都会消除n最右边的一个1,直到n变为0。
直接上代码:
画图分析:
每次运算都减去了最右边的一个1,直至减为0,计算非常高效,这是一个非常巧妙的算法,非常值得我们学习
3.改变13的二进制位第5位,并再改回来
分析:
- 首先13的二进制为:00000000000000000000000000001101
- 我们需要把从右至左的第五位改为1,因此我们可以采用按位或
- 而如何得到这个第5位为1其余数为0的这个二进制数呢?其实我们只需要把1<<4就行了,这样就得到了00000000000000000000000000010000
- 现在如何改回去呢?就像知道规律破译密码一样
- 需要还原的话,我们就需要改变第五位的1为0,我们可以使用按位与&
- 按位与11111111111111111111111111101111,那么这个二进制数如何得到呢?其实只需要000000000000000000010000这个数按位取反~就行
- 这样这题就结束了
总结
以上就是本文关于位运算符的全部内容了,希望对大家有所帮助,有问题可以评论区提出,谢谢大家的支持