C语言 位操作符 >> << & | ^

目录

二进制码

二进制码介绍

整数7的二进制码 

整数-7的二进制码

左移操作符 <<

例1

例2 

右移操作符 >>

位与操作符 &

位或操作符 |

位异或操作符 ^

 Demo:不能创建临时变量,实现两个数的交换


进制

  • 二进制 0~1
  • 八进制 0~7
  • 十进制 0~9
  • 十六进制 0~9 a~f

二进制码

二进制码介绍

  1. 正的整数的源码、反码、补码相同
  2. 负的整数的源码、反码、补码是要计算的
  3. 首个位符号位,符号位为0表示为正数,为1表示为负数
  4. 整数在内存中存储的是补码

整数7的二进制码 

7 的二进制为 111,即 1*2的2次方 + 1*2的1次方 + 1*2的0次方

 一个数字式4个字节,一个字节8个bit,即二进制源码如下 

    00000000000000000000000000000111 源码

    00000000000000000000000000000111 反码

    00000000000000000000000000000111 补码

整数-7的二进制码

    10000000000000000000000000000111 源码

    11111111111111111111111111111000 反码(源码的符号位不变,其他位按位取反就是反码)

    11111111111111111111111111111001 补码(反码+1就是补码)

左移操作符 <<

        左移操作符:左边丢弃,右边补0

        左移把每一位向左移,相当于每一位二进制位上的数都乘2,所以总体是原来的2倍

例1

    int a = 7;
    int b = a << 1;
    printf("a = %d\n", a); // 7
    printf("b = %d\n", b); // 14 得到二进制源码 0000000000000000000000000001110,即14 —— 1*2的3次方 + 1*2的2次方 + 1*2的1次方 + 0*2的0次方

例2 

11111111111111111111111111110010 左移1位后的补码  -1得到反码如下
二进制码 11111111111111111111111111110010 减去1后,最后一位数字0会变成1,并且往前找到第一个为1的数字,将它变成0,同时它后面所有的0都变成1,最终得到二进制码 11111111111111111111111111110001。
这是因为减1的操作是对每一个位数进行判断,如果是1就变成0,如果是0就要向前面的位借位,借位的操作是将前一位(即更高位)的数字减1,借位操作会一直向高位进行,直到遇到第一个为1的数字才停止,并将其变成0。
因此,我们可以将减1的过程表示为以下步骤:

  1. 将最后一位0变成1。
  2. 因为借位的操作会从低位依次向高位进行,所以从最后一位开始,往前找到第一个为1的数字,将其变成0。
  3. 把这个1后面的所有数字(0)都变成1。

比如 11111111111111111111111111110000  - 1 得到

        11111111111111111111111111101111
        11111111111111111111111111110001 左移1位后的反码  符号位不变,其他位取反得到源码如下
        10000000000000000000000000001110 左移1位后的源码

    int A = -7;
    printf("B = %d\n", A << 1); // 得到二进制源码10000000000000000000000000001110 即-14

右移操作符 >>

        右移操作符:分两种

        算术移位:右边丢弃,左边补原符号位(本编译器采用的是算术移位)

        逻辑移位:右边丢弃,左边补0

11111111111111111111111111111100 右移1位后的补码  -1得到反码如下
11111111111111111111111111111011 右移1位后的反码   
10000000000000000000000000000100 右移1位后的源码 即 -4

    int c = 7;
    printf("c = %d\n", c >> 1); // 3
    int C = -7;
    printf("C = %d\n", C >> 1); // -4

位与操作符 &

按(2进制)位与 ———— 按补码进行运算,有一个为0,则为0,都为1则为1

    int a = 3;
    int b = -5;
    int c = a & b;
    /*
        10000000000000000000000000000101 -5的源码
        11111111111111111111111111111010 -5的反码

        11111111111111111111111111111011 -5的补码
        00000000000000000000000000000011 3的补/源码
        00000000000000000000000000000011 与后的补码 (此处符号位是0,即也可看成源码)
     */
    printf("c=%d\n", c); // 3

位或操作符 |

按(2进制)位或 ———— 按补码进行运算,有一个为1,则为1,都为0即0

    int a = 3;
    int b = -5;
    int d = a | b;
    /*
        11111111111111111111111111111011 -5的补码
        00000000000000000000000000000011 3的补/源码
        11111111111111111111111111111011 或后的补码 (此处符号位是1,则需要逆推为源码)
        11111111111111111111111111111010 或后的反码
        10000000000000000000000000000101 或后的源码
     */
    printf("d=%d\n", d); // -5

位异或操作符 ^

按(2进制)位异或 ———— 按补码进行运算,相同为0,相异为1

    int a = 3;
    int b = -5;
    int e = a ^ b;
    /*
        11111111111111111111111111111011 -5的补码
        00000000000000000000000000000011 3的补/源码
        11111111111111111111111111111000 异或后的补码 (此处符号位是1,则需要逆推为源码)
        11111111111111111111111111110111 异或后的反码
        10000000000000000000000000001000 异或后的源码
     */
    printf("e=%d\n", e); // -8

 Demo:不能创建临时变量,实现两个数的交换

位操作符与的规律

        a ^ a = 0

        0 ^ a = a

        a ^ a ^ b = b

        3^3 = 0 -> a^a= 0
        011
        011
        000

        0^5 = 5 -> 0^a = a
        000
        101
        101

        3^3^5 = 5
        3^3^5 = 5 异或操作符支持交换律,如下
        011
        101
        110
        011
        101

    int A = 3;
    int B = 5;
    A = A ^ B;                   // A = 3 ^ 5
    B = A ^ B;                   // B = 3 ^ 5 ^ 5 ————> 3
    A = A ^ B;                   // A = 3 ^ 5 ^ 3 ————> 5
    printf("A=%d B=%d\n", A, B); // 5, 3

你可能感兴趣的:(C语言,c语言,开发语言)