C语言之位操作符:<<、>>、&、|、^、~,以及原码反码补码和例题详解


目录

前言

一、原码、反码、补码

二、移位操作符

三、位操作符:&、|、^、~

四、经典例题分析:

总结


前言

        本文将详细介绍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位,并再改回来

分析:

  1. 首先13的二进制为:00000000000000000000000000001101
  2. 我们需要把从右至左的第五位改为1,因此我们可以采用按位或
  3. 而如何得到这个第5位为1其余数为0的这个二进制数呢?其实我们只需要把1<<4就行了,这样就得到了00000000000000000000000000010000
  4. 现在如何改回去呢?就像知道规律破译密码一样
  5. 需要还原的话,我们就需要改变第五位的1为0,我们可以使用按位与&
  6. 按位与11111111111111111111111111101111,那么这个二进制数如何得到呢?其实只需要000000000000000000010000这个数按位取反~就行
  7. 这样这题就结束了


总结

        以上就是本文关于位运算符的全部内容了,希望对大家有所帮助,有问题可以评论区提出,谢谢大家的支持

上一篇:人大金仓数据库的数据分析的方法和工具


下一篇:利用亚马逊云科技GenAI企业助手Amazon Q Business构建企业代码开发知识库