> 文档中心 > 位运算操作符详解

位运算操作符详解

文章目录

  • 一. 移位操作符>> <<
    • 1. 整数的二进制表示
            • Ps:怎么确定一个数在内存中占几位呢?
    • 2. <<左移操作符
    • 3. >>右移操作符
  • 二. 位操作符& |^
    • 1. &按(二进制)位与
    • 2. |按(二进制)位或
    • 3. ^按(二进制)位异或
      • 1.异或用在解题中用到的性质:
      • 2.位操作符的应用
          • (1) 使特定位翻转
          • (2)不用中间变量,实现两个数的交换
          • (3) 找到只出现特定次数的数字

一. 移位操作符>> <<

操作数只能是整数

对于移位运算符,不要移动负数位,这是标准未定义的

num>>-1//ERROR

1. 整数的二进制表示

整数的二进制有3种表示:

1. 原码1. 反码1. 补码

最高位是符号位,0表示为正数,1表示为负数

Ps:怎么确定一个数在内存中占几位呢?

比如int型整数,占4个字节,每个字节是8比特,所以占4*8=32比特位

int 5的原码:00000000 00000000 00000000 00000101

int -5的原码:10000000 00000000 00000000 00000101

同理,char型是1个字节,就占8位

正整数 负整数
原码 数在内存中的二进制,最高位为0 最高位为1
补码 与原码相同 原码符号位不变,其他位按位取反
反码 与原码相同 反码+1

int a = -5

原码:10000000 00000000 00000000 00000101

反码:11111111 11111111 11111111 11111010

补码:11111111 11111111 11111111 11111011

整数在内存里存储的是补码,打印出来的值是原码

2. <<左移操作符

移位规则:

左边抛弃、右边补0

int a = -10;int b = a<<1;//左移一位printf("%d\n",a);printf("%d\n",b);

结果是:

-10

-20

注意:a本身值是不变的

左移n位就是把原数值*2的n次方

一整个计算过程是这样的

请添加图片描述

这是负数的情况,如果是正数,原、补、反码都一样,到了第4步就不必再-1、取反了。

3. >>右移操作符

移位规则:

右移有两种:

  1. 算数右移:右边丢弃,左边补原符号位
  2. 逻辑右移:右边丢弃,左边补0

是算数右移还是逻辑右移取决于编译器

请添加图片描述

二. 位操作符& |^

操作数只能是整数

1. &按(二进制)位与

int a = 3;int b = -5;int c = a&b;

a和b的补码相运算

对应二进制位上,a和b中只有一个有0就为0,两个都为1时才为1

真值表:

& 0 1
0 0 0
1 0 1
00000000 00000000 00000000 00000011   -> a=3的补码11111111 11111111 11111111 11111011   -> b=-5的补码00000000 00000000 00000000 00000011   -> c的补码同样,输出是原码,这里最高位是0,是正数,所以原码和补码相同

c=3

2. |按(二进制)位或

int a = 3;int b = -5;int c = a|b;

对应二进制位上,a和b中有1就为1

真值表:

| 0 1
0 0 1
1 1 1
00000000 00000000 00000000 00000011   -> a=3的补码11111111 11111111 11111111 11111011   -> b=-5的补码11111111 11111111 11111111 11111011 -> c的补码我们来求c的输出11111111 11111111 11111111 11111010   -> c的反码10000000 00000000 00000000 00000101   -> c的原码

c=-5

3. ^按(二进制)位异或

int a = 3;int b = -5;int c = a^b;

对应二进制位上,相同为0,相异为1

真值表:

^ 0 1
0 0 1
1 1 0
00000000 00000000 00000000 00000011   -> a=3的补码11111111 11111111 11111111 11111011   -> b=-5的补码11111111 11111111 11111111 11111000 -> c的补码我们来求c的输出11111111 11111111 11111111 11110111   -> c的反码10000000 00000000 00000000 00001000   -> c的原码

c=-8

1.异或用在解题中用到的性质:

  1. 任何数与0异或仍是它本身
  2. 任何数与1异或等于将其取反
  3. 任何数与自己异或,等于把自己置0
  4. 异或满足交换律、结合律

2.位操作符的应用

(1) 使特定位翻转

比如:01111010,想使其低4位翻转,即1变为0,0变为1。可以将它与00001111进行^运算

(2)不用中间变量,实现两个数的交换
#include  int main(){  int a = 10;   int b = 20;  a = a^b;//1  b = a^b;//2  a = a^b;//3  printf("a = %d  b = %d\n", a, b); return 0;}//可以这样理解,将1代入2//b = a^b^b  //b = a//将2代入3//a = a^a^b  //a = b
(3) 找到只出现特定次数的数字

一道面试题大家可以试着做做看:https://leetcode-cn.com/problems/missing-number-lcci

参考:https://blog.csdn.net/wwt18811707971/article/details/