16.位运算符

16.运算符-位运算符


16.1 知识点

位运算符是什么

位运算符主要用数值类型进行计算。它将数值转换为二进制,再进行位运算。

位与(&)

基本规则

  • 连接两个数值进行位计算,将数值转为二进制。
  • 对位运算,有 0 则 0。
short a = 1; // 001
short b = 5; // 101
short result = a & b;
cout << result << endl; // 1
//  001
//& 101
//  001 = 1

a = 3;  // 011
b = 19; // 10011   
result = a & b;
cout << result << endl; // 3
//  00011
//& 10011
//  00011 = 3

多个数值进行位运算

没有括号时,从左到右依次计算。

a = 1;     // 00001
b = 5;     // 00101
short c = 19; // 10011   
result = a & b & c;
cout << result << endl; // 1
//  00001
//& 00101
//  00001 = 1
//& 10011
//  00001 = 1

位或(|)

基本规则

  • 连接两个数值进行位计算,将数值转为二进制。
  • 对位运算,有 1 则 1。
  • 多个数值连续计算规则相同。
a = 1; // 001
b = 5; // 101
result = a | b;
cout << result << endl; // 5
//  001
//| 101
//  101 = 5

a = 5;  // 00101
b = 10; // 01010
c = 20; // 10100
result = a | b | c;
cout << result << endl; // 31
//  00101
//| 01010
//  01111
//| 10100
//  11111 = 1 + 2 + 4 + 8 + 16 = 31

异或(^)

基本规则

  • 连接两个数值进行位计算,将数值转为二进制。
  • 对位运算,相同为 0,不同为 1。
a = 5;  // 00101
b = 10; // 01010
result = a ^ b;
cout << result << endl; // 15
//  00101
//^ 01010
//  01111 = 15

a = 10; // 1010
b = 11; // 1011
c = 4;  // 0100
result = a ^ b ^ c;
cout << result << endl; // 5
//  1010
//^ 1011
//  0001
//^ 0100
//  0101 = 5

位取反(~)

基本规则

  • 写在数值前面,将数值转为二进制。
  • 对位运算,0 变 1,1 变 0。
a = 5; // 0000 0000 0000 0101
// 取反得到:1111 1111 1111 1010 是补码。
// 补码转换成源码二进制后,再转为十进制即为最终值。
a = ~a; // 1111 1111 1111 1010 - 1 = 1111 1111 1111 1001 = 1000 0000 0000 0110 = -6
cout << a << endl; // -6

左移(<<)和右移(>>)

左移规则

让一个数的二进制数进行左移,右侧加 0。

a = 5; // 0000 0000 0000 0101
result = a << 5;
// 1 位 1010
// 2 位 10100
// 3 位 101000
// 4 位 1010000
// 5 位 10100000 = 32 + 128 = 160
cout << result << endl; // 160

a = 128; // 0000 0000 1000 0000
// 如果左移时将某位为 1 的数移出范围,会直接丢弃。
result = a << 15;
cout << result << endl; // 0

右移规则

右移几位,右侧去掉相应的位数。

a = 5; // 101
// 1 位 10
// 2 位 1
result = a >> 2;
cout << result << endl; // 1

位运算符支持复合运算符

支持 &=|=^=<<=>>= 等复合运算符。

a = 5;
a &= 1;
// 101
// 001
// 001
cout << a << endl; // 1

位运算符的优先级

运算符本身的优先级

  • 位取反(~)
  • 左移、右移(<<、>>)
  • 位与(&)
  • 位异或(^)
  • 位或(|)
int i = 1 | 2 ^ 3 & 2 << 1;
cout << i << endl; // 3
// 2 << 1 => 10 << 1 = 100
// 3 & 100 => 011 & 100 = 000 = 0
// 2 ^ 000 => 10 ^ 00 = 10
// 1 | 10 => 01 | 10 = 11 = 3

与其他运算符的优先级比较

  • 从高到低排列:

    1. 算术运算符。
    2. 位运算符。
    3. 关系运算符。
    4. 逻辑运算符。
  • 注意:cout 中的 << 被重新定义,不再是左移功能,而是用于控制台打印。

  • 它的优先级仍基于位运算符,因此需要注意优先级问题。

// <<优先级高于||,先执行cout << false,输出0并返回cout对象,
// 再与true做||运算,结果未体现,只看到0输出
cout << false || true;//0

// 括号改变优先级,先算括号里false || true,结果为true,
// 再由cout输出,true转整数1输出,所以看到1
cout << (false || true);//1

16.2 知识点代码

Lesson16_运算符_位运算符.cpp

#include <iostream>
using namespace std;
int main()
{
    std::cout << "位运算符\n";

    #pragma region 知识点一 位运算符是什么

    //位运算符 主要用数值类型进行计算的
    //将数值转换为2进制 再进行位运算

    #pragma endregion

    #pragma region 知识点二 位与 &

    // 1.基本规则 
    //   连接两个数值进行位计算 将数值转为2进制 
    //   对位运算 有0则0

    short a = 1;//001
    short b = 5;//101
    short result = a & b;
    cout << result << endl;//1
    //  001
    //& 101
    //  001 = 1

    a = 3;  //011
    b = 19; //10011   
    result = a & b;
    cout << result << endl;//3
    //  00011
    //& 10011
    //  00011 = 3


    // 2.多个数值进行位运算 
    //   没有括号时 从左到右 依次计算
    a = 1;     // 00001
    b = 5;     // 00101
    short c = 19;// 10011   
    result = a & b & c;
    cout << result << endl;//1
    //  00001
    //& 00101
    //  00001 = 1
    //& 10011
    //  00001 = 1

    #pragma endregion

    #pragma region 知识点三 位或 |

    // 基本规则 
    // 连接两个数值进行位计算 将数值转为2进制 
    // 对位运算 有1则1
    // 多个数值连续计算和之前规则相同

    a = 1;//001
    b = 5;//101
    result = a | b;
    cout << result << endl;//5
    //  001
    //| 101
    //  101 = 5

    a = 5;  //00101
    b = 10; //01010
    c = 20; //10100
    result = a | b | c;
    cout << result << endl;//31
    //  00101
    //| 01010
    //  01111
    //| 10100
    //  11111 = 1 + 2 + 4 + 8 + 16 = 31

    #pragma endregion

    #pragma region 知识点四 异或 ^

    // 基本规则 
    // 连接两个数值进行位计算 将数值转为2进制 
    // 对位运算 相同为0 不同为1

    a = 5;  //00101
    b = 10; //01010
    result = a ^ b;
    cout << result << endl;//15
    //  00101
    //^ 01010
    //  01111 = 15

    a = 10; // 1010
    b = 11; // 1011
    c = 4;  // 0100
    result = a ^ b ^ c;
    cout << result << endl;//5
    //  1010
    //^ 1011
    //  0001
    //^ 0100
    //  0101 = 5

    #pragma endregion

    #pragma region 知识点五 位取反 ~

    // 基本规则 
    // 写在数值前面 将数值转为2进制 
    // 对位运算 0变1 1变0

    a = 5; // 0000 0000 0000 0101
    // 0000 0000 0000 0101 取反得到的是 1111 1111 1111 1010 1111 1111 1111 1010是补码 要转换成源码二进制后转成10进制 就是打印出来的最终值
    //            补码                            反码                    原码
    a = ~a; // 1111 1111 1111 1010 - 1  =  1111 1111 1111 1001 =  1000 0000 0000 0110 = -6
    cout << a << endl;//-6

    #pragma endregion

    #pragma region 知识点六 左移 << 和 右移 >>

    // 规则 让一个数的2进制数进行左移和右移

    // 左移几位 右侧加几个0
    a = 5; // 0000 0000 0000 0101
    result = a << 5;
    // 1位 1010
    // 2位 10100
    // 3位 101000
    // 4位 1010000
    // 5位 10100000 = 32 + 128 = 160
    cout << result << endl;//160
    a = 128;// 0000 0000 1000 0000
    //如果左移 将某一位为1的数 移出超过位数范围了 会直接丢弃掉
    result = a << 15;
    cout << result << endl;//0

    // 右移几位 右侧去掉几个数
    a = 5;//101
    // 1位 10
    // 2位 1
    result = a >> 2;
    cout << result << endl;//1

    #pragma endregion

    #pragma region 知识点七 位运算符支持复合运算符

    // &= 、 |= 、 ^= 、 <<= 、 >>=
    //注意:复合运算符也可称为 双目运算符
    //它们两的作用是一样的 都是用自己和另外一个数去进行位运算
    //a = a & 1;
    a = 5;
    a &= 1;
    //101
    //001
    //001
    cout << a << endl;//1

    #pragma endregion

    #pragma region 知识点八 位运算符的优先级

    //位运算符本身
    //运算优先级从高到低排列
    // 位取反 ~
    // 左移右移  <<、>>
    // 位与      &
    // 位异或    ^
    // 位或      |
    int i = 1 | 2 ^ 3 & 2 << 1;
    cout << i << endl;//3
    // 2 << 1 => 10 << 1 = 100
    // 3 & 100 => 011 & 100 = 000 = 0
    // 2 ^ 000 => 10 ^ 00 = 10
    // 1 | 10 => 01 | 10 = 11 = 3

    //和其他运算符比较 
    //运算优先级从高到低排列
    //算数运算符
    //位运算符
    //关系运算符
    //逻辑运算符

    // 注意:cout 中的 << 符号 被重新定义了 不在是左移功能 而是用于进行控制台打印
    // 但是它的优先级还是基于 位运算符 来判断的 
    // 所以 我们在使用它打印时 需要注意优先级问题 最后在后面打一个括号

    // <<优先级高于||,先执行cout << false,输出0并返回cout对象,
    // 再与true做||运算,结果未体现,只看到0输出
    cout << false || true;//0

    // 括号改变优先级,先算括号里false || true,结果为true,
    // 再由cout输出,true转整数1输出,所以看到1
    cout << (false || true);//1

    #pragma endregion
}

16.3 练习题

35 << 4 和 66 >> 1 的结果为?

// .... 1    1   1   1  1   1  1  1  1
//    256  128  64  32  16  8  4  2  1 
// 100011 << 4 = 1000110000 = 16 + 32 + 512 = 560
cout << (35 << 4) << endl; // 560

// 1000010 >> 1 = 100001 = 1 + 32 = 33
cout << (66 >> 1) << endl; // 33

99 ^ 33 和 76 | 85 的结果为?

// 99 ^ 33
//  1100011 
//^ 0100001
//  1000010 = 2 + 64 = 66
cout << (99 ^ 33) << endl; // 66

// 76 | 85
//  1001100
//| 1010101
//  1011101 = 1 + 4 + 8 + 16 + 64 = 93
cout << (76 | 85) << endl; // 93

76 ^ 12 ^ 12 的结果为?

// 潜在知识点:异或加密
// 一个数异或另外一个数A得到的结果,再异或A就可以得到原来的数
// A相当于就是一个密钥,可以用来加密和解密
//  1001100
//^ 0001100 
//  1000000
//^ 0001100 
//  1001100 = 76
cout << (76 ^ 12 ^ 12) << endl; // 76

16.4 练习题代码

Lesson16_练习题.cpp

#include <iostream>
using namespace std;
int main()
{
    std::cout << "位运算符练习题\n";

    #pragma region 练习题一

    //35 << 4 和 66 >> 1 的结果为?

    // .... 1    1   1   1  1   1  1  1  1
    //    256  128  64  32  16  8  4  2  1 
    // 100011 << 4 = 1000110000 = 16 + 32 + 512 = 560
    cout << (35 << 4) << endl;//560

    // 1000010 >> 1 = 100001 = 1 + 32 = 33
    cout << (66 >> 1) << endl;//33

    #pragma endregion

    #pragma region 练习题二

    //99 ^ 33 和 76 | 85 的结果为?

    // 99 ^ 33
    //  1100011 
    //^ 0100001
    //  1000010 = 2 + 64 = 66
    cout << (99 ^ 33) << endl;//66

    // 76 | 85
    //  1001100
    //| 1010101
    //  1011101 = 1 + 4 + 8 + 16 + 64 = 93
    cout << (76 | 85) << endl;//93

    #pragma endregion

    #pragma region 练习题三

    //76 ^ 12 ^ 12 的结果为?

    // 潜在知识点:异或加密
    // 一个数异或另外一个数A得到的结果 再异或A 就可以得到原来的数
    // A相当于就是一个密钥,可以用来加密和解密
    //  1001100
    //^ 0001100 
    //  1000000
    //^ 0001100 
    //  1001100 = 76
    cout << (76 ^ 12 ^ 12) << endl;//76

    #pragma endregion

}


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com

×

喜欢就点赞,疼爱就打赏