• c 位运算


    声明:位运算根据不同的操作系统得出的结果可能不同,在此我是根据 8位机 来做的介绍

    优先级:! > 算术运算符 > 关系运算符 > && > || > 赋值运算符

    一、位运算:

      位运算的运算分量只能是整型或字符型数据,位运算把运算对象看作是由二进位组成的位串信息,按位完成指定的运算,得到位串信息的结果。

      常用的位运算有 AND(&)、OR(|)、NOT(~)、EXCLUSIVE-OR(异或^)、同一运算(I 大写的i)、移运算(左移运算 << 、右移运算 >>)

      位运算符的优先级从高到低,依次为~、&、^、|, 其中~的结合方向自右至左,且优先级高于算术运算符,其余运算符的结合方向都是自左至右,且优先级低于关系运算符。

    二、介绍运算(转换成2进制位进行运算

    1. AND(&) 按位与运算(将两个运算分量的对应位按照一定的规则就行运算):

      规则:相同位置的位的值都是1,则结果为1,否则即为0

      比如:1 & 0 、3 & 2 、4 & 2 、6 & 2

      转换2进制:00000001  & 00000000(1 & 0)、00000011 & 00000010(3 & 2)、00000100 & 00000010(4 & 2)、00000110 & 00000010(6 & 2

      换种形式:00000001、00000011、00000100、00000110 

           00000000、00000010、00000010、00000010

      结果:1 & 0 = 0、3 & 2 = 2、4 & 2 = 0、6 & 2 = 2

      按位与运算就是集合的交集,很简单,A = {0,2,3,6}, B = {0,1,4,6},那么A与B的交集就是{0,6}

    2. OR(|)按位或运算(将两个运算分量的对应位按照一定的规则就行运算):

      规则:相同位置的位的值只要有1个值是1,结果就是1,否则即为0

      比如:1 | 0 、2 | 1 、6 | 2 、8 | 3

      转换2进制:00000001 | 00000000(1 | 0)、00000010 | 00000001(2 | 1)、00000110 | 00000010(6 | 2 )、00001000 | 00000011(8 | 3

      换种形式:00000001 00000010 00000110 00001000 

             00000000 00000001 00000010 00000011

      结果:1 | 0 = 1、2 | 1 = 3、6 | 2 =  6、8 |  3 = 11

      按位或运算就是集合的并集,根据规则就可以看得出了,比如10000001 | 011111110,那结果就是这两个二进制数的合并,也就是11111111

    3. EXCLUSIVE-OR(异或^)按位异或运算(将两个运算分量的对应位按照一定的规则就行运算):

      规则:相同位置的位的值相同的,结果为0,不相同的结果为1

      比如:1 ^ 2、0 ^ 0、3 ^ 6、9 ^ 1

      转换2进制:00000001 ^ 00000010(1 ^ 2)、00000000 ^ 00000000(0 ^ 0)、00000011 ^ 00000110(3 ^ 6)、00001001 ^ 00000001(9 ^ 1

      换种形式:00000001 、00000000 、00000011 、00001001 

           00000010 、00000000 、00000110 、00000001

      结果:1 ^ 2 = 3、0 ^ 0 = 0、3 ^ 6 = 5、9 ^ 1 = 8

     4. NOT(~)按位取反运算(按位取反运算是单目运算,用来求一个位串信息按位的反)

      规则:二进制位的值,为1的结果是0,为0的结果是1

       比如: ~7 、~9、~0、~10

      转换2进制:00000111(7)、00001001(9)、000000(0)、00001010(10)

      转换结果:  11111000(~7)、11110110(~9)、11111111(~0)、11110101(~10)

      结果(16进制,10进制懒得算):~7 = 0xf8、~9 = 0xf6、~0 = 0xff、~10 = 0xf5

      按位取反运算就是“补运算”了,通过规则,比如:10001110 补运算的结果是:01110001,把二进制数和其补运算的结果合并在一起刚好是11111111

    5. identity operation (I)同一运算:

      规则:

        (1). 如果两个值类型不相同,则它们不相等

        (2). NaN和其他任何值都是不相等的,包括它本身

        (3). 如果两个引用值指向同一个对象,数组或函数,则它们是相等的。如果指向不同的对象,则它们是不等的,尽管两个对象具有完全一样的属性

        如果不相同,则无法进行其他操作

      比如:a ^ I (a) = a ^ a = 0;

    6. 移位运算(移位运算是双目运算,有两个运算分量,左分量为移位数据对象,右分量的值为移位位数。移位运算将左运算分量视作由二进位组成的位串信息,对其作向左或向右移位,得到新的位串信息,移位运算符的优先级低于算术运算符,高于关系运算符,它们的结合方向是自左至右。)

      1. 左移运算符(<<):

        规则:将一个位串信息向左移动指定的位置,右端空出的位补0,左端溢出的高位舍弃,且

        比如:-2  << 4 

        过程:-2 先转换成二进制(2进制的补码),00000010 -补码-> 11111101 + 1 -结果-> 11111110  -根据规则,往左移动4位,右端空出的位补0-> 111111100000 -根据系统位数8位机,左端溢出的高位要被舍去,结果保留8位-> 11100000 -转换成10进制是224,这是补码的结果,我们在逆运算转回去,这是负数,前面加上负号-> -00011111 - 结果是 -31,再减去1 -> -31-1 = -32

        结果:-2  << 4 = -32; (可能大家很疑惑2进制的补码怎么算,这里给个简单的公式,先把二进制取反,在加1,也就是先~按位取反操作再加上1,-2 = 00000010 = 11111101 + 1 = 11111110 = 254)

        比如:2 << 4

        过程:无符号整数就好算多了, 2 -二进制-> 00000010 - 根据规则往左移动4位,其实也就是在二进制的右端加4个0 -> 000000100000 - 根据系统位数8位机,高位要舍去,保留8位二进制数 -> 00100000- 转换成10进制 -> 32

      2. 右移位运算(>>):

        规则(分有符号数和无符号数):将一个位串信息向右移动指定的位置,右端溢出的位舍去

          1> 无符号右移:左端空出的位补0

          2> 有符号右移:

            移位前符号为0(正数):左端空出的位也补0; 

            移位前符号为1(负数):左端用0或者1补充,取决于计算机系统;负数右移补充0,称为“逻辑右移”;负数右移补充1,称为“算术右移”;

                         可以使用以下方法来测试自己系统针对负数右移的具体方法:printf("%d ", -2 >> 4);

        无符号右移示例:

          比如:3 >> 3

          过程: 00000011 - 根据规则往右移动三位,左侧补充0 -> 00000000011 -右侧溢出舍去 -> 00000000 - 转换 -> 0

          结果: 3 >> 3 = 0;

        有符号右移:

          正数:跟上边无符号右移一样,不做演示

          负数:(上边说过负数如何转成2进制数表示,就是2进制的补码,先按位取反运算,再加1)

            比如:-2 >> 4

            过程:00000010 - 取反 -> 11111101 + 1 - 结果-> 11111110 ,计算到这里根据系统不同可能是“逻辑右移”,可能是“算术右移”

               逻辑右移:11111110 - 负数右移,左侧补充0为逻辑右移 -> 000011111110 - 根据系统位数8位,根据右移规则,右端溢出舍去,从左往右数8位,便是结果 -> 00001111 - 结果 -> 15

               逻辑右移结果:-2 >> 4 = 00001111(15) - 转换回2进制补码 -> -(11110000) -1 - 结果 -> -241

               算术右移:11111110 - 负数右移,左侧补充1为算术右移 -> 111111111110 - 根据系统位数8位,根据右移规则,右端溢出舍去,从左往右数8位,便是结果 -> 11111111 - 结果 -> 255

                  算术右移结果:-2 >> 4 = 11111111(255) - 转换回2进制补码 -> 00000000 -1 - 结果 -> -1

     三、题目

      1.只使用位级和逻辑运算,编写一个C表达式,他等价于x==y。换句话说,当x和y相等时他将返回1,否则返回0

       答:因为 x ^ y 只会在x == y时为0,所以我们可以利用这一性质得到这个表达式其实就是 !(x ^ y)

  • 相关阅读:
    Alpha阶段敏捷冲刺③
    Alpha阶段敏捷冲刺②
    Alpha阶段敏捷冲刺①Scrum 冲刺博客
    201621123031 《Java程序设计》第8周学习总结
    201621123031 《Java程序设计》第7周学习总结
    201621123031 《Java程序设计》第6周学习总结
    201621123031 《Java程序设计》第5周学习总结
    201621123031 《Java程序设计》第4周学习总结
    201621123031 《Java程序设计》第3周学习总结
    201621123031 《Java程序设计》第2周学习总结
  • 原文地址:https://www.cnblogs.com/zengguowang/p/7200518.html
Copyright © 2020-2023  润新知