【C进阶】16、位运算符

Summary

1)C语言中的位运算符:

运算符 意义 规则
& 按位与 全1得1,有0得0
I 按位或 有1得1,全0得0
^ 按位异或 相同为0,不同得1
~ 取反 1变0, 0变1
<< 左移 高位丢弃,低位补0
·>> 右移 高位补符号位,低位舍弃

2)左移、右移的注意点:

  • 左操作数必须是整数类型

    • char和short被隐式转换为int后进行操作
  • 右操作数的范围必须为:[0,31]否则结果未定义(不同编译器处理结果不同)
  • 左移运算符<<将运算数的二进制位左移,效果相当于乘以2的n次方效率更高
  • 右移运算符>>将运算数的二进制位右移,效果相当于除以2的n次方效率更高
  • 避免位运算符、逻辑运算符、数学运算符等混合运算,如果必须这样,使用括号表示好计算顺序。(单算移比、按逻三赋

3)位运算注意点:

  • 位运算没有短路规则,每个操作数都会参与运算
  • 位运算的结果是整数,而不是0或1
  • 位运算的优先级高于逻辑运算(单算移比 按逻三赋

4)交换两个整形变量的值:

  • Demo1:部分和方式:不使用中间变量,但存在溢出的问题

    #define SWAP(a, b) \
    {                  \
      a = a + b;       \
      b = a - b;       \
      a = a - b;       \
    }
  • Demo2:位运算方式:使用异或(两个相同的值异或结果为0,任何数和0异或仍为本身

    #define SWAP(a, b)    \
    {                     \
      a = a ^ b;          \
      b = a ^ b;          \
      a = a ^ b;          \
    }

位运算符剖析

C语言最初设计用来开发UNIX操作系统,操作系统运行于硬件平台之上,必然会涉及位运算,需要对硬件的bit位(0和1)进行操作。C语言中位运算直接映射到了硬件系统中的位运算。
位运算符直接对bit位进行操作,其效率最高

1、C语言中的位运算符

运算符 意义 规则
& 按位与 全1得1,有0得0
I 按位或 有1得1,全0得0
^ 按位异或 相同为0,不同得1
~ 取反 1变0, 0变1
<< 左移 高位丢弃,低位补0
·>> 右移 高位补符号位,低位舍弃

2、左移和右移的注意点

  • 左操作数必须是整数类型

    • char和short被隐式转换为int后进行操作
  • 右操作数的范围必须为:[0,31]否则结果未定义(不同编译器处理结果不同)
  • 左移运算符<<将运算数的二进制位左移,效果相当于乘以2的n次方效率更高
  • 右移运算符>>将运算数的二进制位右移,效果相当于除以2的n次方,效率更高

    • Demo1
      d << 2;               // error, 左操作数必须是整型
      int x = 10 >> 1;      // ok,"右移等效除以2的n次方",输出5
      int y = -1 << 1;      // ok,"左移等效乘以2的n次方",输出-2
    
      int z = 3 << -1;      // -1不在[0,31]范围中,结果未定义,不同编译器不同处理
              // 编译器亦提示了错误:Possible overflow in shift operation
      
      // gcc 1,            左移-1相当于右移1,那就除以2,得到了1
      // bcc -2147483648,  int的最小值
      // vc 0,             本来就未定义,给你0把
  • 避免位运算符、逻辑运算符、数学运算符等混合运算,如果必须这样,使用括号表示好计算顺序。(单算移比、按逻三赋

    • Demo2
    0x1 << 2 + 3 输出多少?
    等价于 0x1 << (2 + 3),输出为32
    
    // 如果这行代码作者本意是先左移,再加法,实际执行结果就不是期望的
    // 所以在写代码时要尽量用括号()来表示清楚计算次序

3、位运算注意点

  • 位运算没有短路规则,每个操作数都会参与运算
  • 位运算的结果是整数,而不是0或1
  • 位运算的优先级高于逻辑运算(单算移比 按逻三赋

    int i = 0;
    int j = 0;
    int k = 0;
    
    if(++i | ++j & ++k)        // 所有的运算数都会执行到,因此i j k判断后都为1
      printf("cc");

4、 位运算应用简单示例

交换两个整形变量的值

  • Demo1:部分和方式:不使用中间变量,但存在溢出的问题

    #define SWAP(a, b) \
    {                  \
      a = a + b;       \
      b = a - b;       \
      a = a - b;       \
    }
  • Demo2:位运算方式:使用异或(两个相同的值异或结果为0,任何数和0异或仍为本身

    #define SWAP(a, b)    \
    {                     \
      a = a ^ b;          \
      b = a ^ b;          \
      a = a ^ b;          \
    }

本文总结自“狄泰软件学院”唐佐林老师《C语言进阶课程》。
如有错漏之处,恳请指正。

你可能感兴趣的:(c)