第16课 - 位运算符分析

第16课 - 位运算符分析

1. C语言中的位运算符

    

 C语言中的位运算符直接对 bit 位进行操作,其效率最高。

2. 左移和右移运算符的注意点

(1)左操作数必须为整型类型即char、short、int,其中char和short被隐式转换为int后进行移位操作。其它的数据类型,如float等不能进行移位操作。

(2)C标准规定右操作数的范围为[0,31],如果右操作数不在该范围内,其行为是未定义的,不同的编译器处理方式不同。

(3)左移运算符 << 将运算数的二进制位左移      

    规则:高位丢弃,低位补0

(4)右移运算符 >> 将运算数的二进制位右移

    规则:高位补符号位(正数补0,负数补1),低位丢弃

(5)0x1 << 2 + 3 的值是什么?是1左移两位之后的值4 + 3 = 7吗?   ==>  注意,+ 的优先级大于 << 和 >> 的优先级,即0x1 << 5 等于32

(6)左移n位相当于乘以2的n次方,但效率比数学运算符高;右移n位相当于除以2的n次方,但效率比数学运算符高

【位运算符初探】

 1 #include <stdio.h>
 2 
 3 int main()
 4 {
 5     printf("%d\n", 3 << 2);   // 3 << 2  ==> 11 << 2 ==> 1100,即12
 6     printf("%d\n", 3 >> 1);   // 11 >> 1,即1
 7     printf("%d\n", -1 >> 10);       // -1 >> 10 ==> 11111111 11111111 11111111 11111111 >> 10  ==> 11111111 11111111 11111111 11111111 ,即0xffffffff,仍为-1
 8     printf("%d\n", 0x01 << 2 + 3);  // 相当于0x01 << (2+3),即32
 9     
10     printf("%d\n", 3 << -1);  // oops! 右操作数取值范围为[0,31],-1不在该范围内,不同编译器处理方式不同
11                               // 使用gcc编译,结果为1(将左移-1位当做右移1位,3右移1位结果为1); 使用VS2010编译,结果为0(不符合C标准直接输出0); 使用bcc32编译,结果为-2147483648(int类型的最小值,提醒程序员用法错误)
12     return 0;
13 }

使用gcc编译执行上述代码 

  

※※ 避免位运算符逻辑运算符数学运算符同时出现在一个表达式中,如果确实需要同时参与运算,尽量使用括号( )来表达计算次序。

3. 交换两个整型变量的值

下面再介绍一下使用位运算符交换两个变量的值。

 1 #include <stdio.h>
 2 
 3 // 使用中间变量交换
 4 #define SWAP1(a, b)    \
 5 {                      \
 6     int t = a;         \
 7     a = b;             \
 8     b = t;             \
 9 }
10 
11 // 使用部分和交换
12 #define SWAP2(a, b)    \
13 {                      \
14     a = a + b;         \  // a + b 的值不能溢出
15     b = a - b;         \
16     a = a - b;         \
17 }
18 
19 //使用异或 ^ 交换
20 #define SWAP3(a, b)    \
21 {                      \
22     a = a ^ b;         \
23     b = a ^ b;         \
24     a = a ^ b;         \
25 }
26 
27 int main()
28 {
29     int a = 1;
30     int b = 2;
31     
32     
33     printf("a = %d\n", a); 
34     printf("b = %d\n", b); 
35     
36     SWAP3(a ,b);
37     
38     printf("a = %d\n", a); 
39     printf("b = %d\n", b); 
40     
41     return 0;
42 }

  swj@ubuntu:~/c_course/ch_16$ ./a.out
  a = 1
  b = 2
  a = 2
  b = 1

4. 位运算与逻辑运算

(1)位运算没有短路规则,每个操作数都参与运算

(2)位运算的结果为整数,而不是 0 或 1

(3)位运算的优先级高于逻辑运算的优先级

【混淆概念的判断条件】

位运算

 1 #include <stdio.h>
 2 
 3 int main()
 4 {
 5     int i = 0;
 6     int j = 0;
 7     int k = 0;
 8     
 9     // 位运算没有短路规则,所有操作数都参与运算
10     if( ++i | ++j & ++k )
11     {
12         printf("Run here...\n");
13     }
14     
15     printf("i = %d\n", i);   // 1
16     printf("j = %d\n", j);   // 1
17     printf("k = %d\n", k);   // 1
18 
19     return 0;
20 }

逻辑运算

 1 #include <stdio.h>
 2 
 3 int main()
 4 {
 5     int i = 0;
 6     int j = 0;
 7     int k = 0;
 8     
 9     // 短路规则, (true && ++i) || (++j && ++k)
10     if( ++i || ++j && ++k )
11     {
12         printf("Run here...\n");
13     }
14     
15     printf("i = %d\n", i);  // 1
16     printf("j = %d\n", j);  // 0
17     printf("k = %d\n", k);  // 0
18 
19     return 0;
20 }

 

posted @ 2019-11-13 22:51  Hengs  阅读(313)  评论(0编辑  收藏  举报