1、C语言中的位运算符
位运算符直接对bit位进行操作,其效率最高。
左移和右移注意点
-左操作数必须为整数类型
char和short被隐式转换为int后进行移位操作
-右操作数的范围必须为: [0, 31]
-左移运算符<<将运算数的二进制位左移
规则:高位丢弃,低位补0
-右移运算符>>把运算数的二进制位右移
规则:高位补符号位,低位丢弃
2、有趣的问题
0x1<<2+3的值会是什么?
A:先算0x1<<2再把中间结果加3 ,最终为7。
B:我觉得先算2 + 3 ,所以结果为32。// 10 0000
C:可以这么混合计算吗?
这个问题的真的目的是干嘛呢?它的求值次序是怎样的?我们让编译器来告诉我们
1 #include <stdio.h> 2 3 int main() 4 { 5 printf("%d\n", 3 << 2); 6 printf("%d\n", 3 >> 1); 7 printf("%d\n", -1 >> 1); 8 printf("%d\n", 0x01 << 2 + 3); 9 10 printf("%d\n", 3 << -1); // oops! 11 12 return 0; 13 }
这里分别有三款编译器:
bcc, gcc,vcc,他们的差异很大,读者可以直接试下。但第10行结果应该是32,gcc对左移-1,当作右移1位,其他的报错或者结果不对。
小贴士:
防错准则:
-避免位运算符,逻辑运算符和数学运算符同时出现在一个表达式中
-当位运算符,逻辑运算符和数学运算符需要同时参与运算时,
– 尽量使用括号()来表达计算次序
小技巧:
-左移n位相当于乘以2的n次方,但效率比数学运算符高
-右移n位相当于除以2的n次方,但效率比数学运算符高
编程实验-交换两个整形变量.cpp:
1 #include <stdio.h> 2 3 #define SWAP1(a, b) \ 4 { \ 5 int t = a; \ 6 a = b; \ 7 b = t; \ 8 } 9 10 #define SWAP2(a, b) \ 11 { \ 12 a = a + b; \ 13 b = a - b; \ 14 a = a - b; \ 15 } 16 17 #define SWAP3(a, b) \ 18 { \ 19 a = a ^ b; \ 20 b = a ^ b; \ 21 a = a ^ b; \ 22 } 23 24 int main() 25 { 26 int a = 1; 27 int b = 2; 28 29 30 printf("a = %d\n", a); 31 printf("b = %d\n", b); 32 33 SWAP3(a ,b); 34 35 printf("a = %d\n", a); 36 printf("b = %d\n", b); 37 38 return 0; 39 }
3.位运算与逻辑运算
位运算与逻辑运算不同:
-位运算没有短路规则,每个操作数都参与运算
-位运算的结果为整数,而不是0或1
-位运算优先级高于逻辑运算优先级
4.实例分析:
混淆概念的逻辑判断
1 #include <stdio.h> 2 3 int main() 4 { 5 int i = 0; 6 int j = 0; 7 int k = 0; 8 9 if( ++i | ++j & ++k ) 10 { 11 printf("Run here...\n"); 12 } 13 14 return 0; 15 }
5.小结
位运算符只能用于整数类型
左移和右移运算符的右操作数范围必须为[0, 31]
位运算没有短路规则,所有操作数均会求值
位运算的效率高于四则运算和逻辑运算
运算优先级:四则运算>位运算>逻辑运算