跳至主要內容

2.13 位运算符


位运算符

  • 程序中的所有数据在计算机内存中都是以二进制的形式储存的。
  • 位运算就是直接对整数在内存中的二进制位进行操作
  • C语言提供了6个位操作运算符, 这些运算符只能用于整型操作数
符号名称运算结果
&按位与同1为1
|按位或有1为1
^按位异或不同为1
~按位取反0变1,1变0
<<按位左移乘以2的n次方
>>按位右移除以2的n次方

  • 按位与:
    • 只有对应的两个二进位均为1时,结果位才为1,否则为0
    • 规律: 二进制中,与1相&就保持原位,与0相&就为0
9&5 = 1

 1001
&0101
------
 0001

  • 按位或:
    • 只要对应的二个二进位有一个为1时,结果位就为1,否则为0
9|5 = 13

 1001
|0101
------
 1101

  • 按位异或
    • 当对应的二进位相异(不相同)时,结果为1,否则为0
    • 规律:
      • 相同整数相的结果是0。比如55=0
      • 多个整数相^的结果跟顺序无关。例如: 567=576
      • 同一个数异或另外一个数两次, 结果还是那个数。例如: 577 = 5
9^5 = 12

 1001
^0101
------
 1100

  • 按位取反
    • 各二进位进行取反(0变1,1变0)
~9 =-10
0000 0000 0000 0000 0000 1001 // 取反前
1111 1111 1111 1111 1111 0110 // 取反后

// 根据负数补码得出结果
1111 1111 1111 1111 1111 0110 // 补码
1111 1111 1111 1111 1111 0101 // 反码
1000 0000 0000 0000 0000 1010 // 源码 == -10

  • 位运算应用场景:

    • 判断奇偶(按位或)
       偶数: 的二进制是以0结尾
       8   -> 1000
       10  -> 1010
       
       奇数: 的二进制是以1结尾
       9   -> 1001
       11  -> 1011
    
       任何数和1进行&操作,得到这个数的最低位
       1000
      &0001
       -----
       0000  // 结果为0, 代表是偶数
    
       1011
      &0001
       -----
       0001 // 结果为1, 代表是奇数
    
    • 权限系统
      enum Unix {
        S_IRUSR = 256,// 100000000 用户可读
        S_IWUSR = 128,//  10000000 用户可写
        S_IXUSR = 64,//    1000000 用户可执行
        S_IRGRP = 32,//     100000 组可读
        S_IWGRP = 16,//      10000 组可写
        S_IXGRP = 8,//        1000 组可执行
        S_IROTH = 4,//         100 其它可读
        S_IWOTH = 2,//          10 其它可写
        S_IXOTH = 1 //           1 其它可执行
       };
    // 假设设置用户权限为可读可写
    printf("%d\n", S_IRUSR | S_IWUSR); // 384 // 110000000
    
    • 交换两个数的值(按位异或)
     a = a^b;
     b = b^a;
     a = a^b;
    

  • 按位左移
    • 把整数a的各二进位全部左移n位,高位丢弃,低位补0
      • 由于左移是丢弃最高位,0补最低位,所以符号位也会被丢弃,左移出来的结果值可能会改变正负性
    • 规律: 左移n位其实就是乘以2的n次方
2<<1; //相当于 2 *= 2 // 4
  0010
<<0100

2<<2; //相当于 2 *= 2^2; // 8
  0010
<<1000
  • 按位右移
    • 把整数a的各二进位全部右移n位,保持符号位不变
      • 为正数时, 符号位为0,最高位补0
      • 为负数时,符号位为1,最高位是补0或是补1(取决于编译系统的规定)
    • 规律: 快速计算一个数除以2的n次方
2>>1; //相当于 2 /= 2 // 1
  0010
>>0001
4>>2; //相当于 4 /= 2^2 // 1
  0100
>>0001
  • 练习:
    • 写一个函数把一个10进制数按照二进制格式输出
#include <stdio.h>
void printBinary(int num);
int main(int argc, const char * argv[]) {
    printBinary(13);
}
void printBinary(int num){
    int len = sizeof(int)*8;
    int temp;
    for (int i=0; i<len; i++) {
        temp = num; //每次都在原数的基础上进行移位运算
        temp = temp>>(31-i); //每次移动的位数
        int t = temp&1; //取出最后一位
        if(i!=0&&i%4==0)printf(" "); printf("%d",t);
    }
}
上次编辑于: