1

【C进阶】16、位运算符

 2 years ago
source link: https://segmentfault.com/a/1190000040789476
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Summary

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

运算符意义规则&按位与全1得1,有0得0I按位或有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得0I按位或有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语言进阶课程》。
如有错漏之处,恳请指正。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK