注意按位运算符|和&与逻辑运算符||和&&完全是两码事,别混淆了。
结合律:a&b&c <=> (a&b)&c <=> a&(B&c)
交换律:a&b <=> b&a
左移和右移
左移运算符“<<”是双目运算符。其功能把“<< ”左边的运算数的各二进位全部左移若干位,“<<”右边的数指定移动的位数,高位丢弃,低位补0 。
右移运算符“>>”是双目运算符。其功能把“>> ”左边的运算数的各二进位全部右移若干位,“>>”右边的数指定移动的位数。但注意:对于有符号数,当为正数时, 最高位补0 ;而为负数时,符号位为1。
0x1<<2+3的值是多少?
不是7,是32,因为+优先级高于<<。
防错准则:
1.避免位运算符,逻辑运算符和数学运算符同时出现在一个表达式中
2.当位运算符,逻辑运算符和数学运算符需要同时参与运算时,尽量使用括号()来表达计算次序
0x01<<2+30;或0x01<<2-3;
这样行吗?不行。一个整型数长度为32 位,左移32 位发生了什么事情?溢出!左移-1位呢?反过来移?所以,左移和右移的位数是有讲究的。左移和右移的位数不能大于数据 的长度,不能小于0 。
小技巧:
左移n位相当于乘以2的n次方,右移相当于除以2的n次方,效率比数学运算符高
3种交换两个变量程序分析
#define SWAP1(a,b) \
{ \
int temp = a; \
a = b; \
b = temp; \
} //最常规,但要借助第三个变量,如果资源设备受限则不好,但是适用于任何类型的数
#define SWAP2(a,b) \
{ \
a = a + b; \
b = a - b; \ // b = a+b-b; => b = a;
a = a - b; \ // a= a+b-a; => a = b;
} // 如果a,b较大,则a+b可能会产生溢出
#define SWAP3(a,b) \
{ \
a = a ^ b; \
b = a ^ b; \ // => b = a^b^b; => b = a^(b^b); => b = a^0; => b = a;
a = a ^ b; \ // => a = a^b^a; => a = a^a^b; => a = 0^b; => a = b;
} //不会溢出,效率高,适用于整型
面试题
有一个数列,其中的自然数都是以偶数的形式出现,只有一个自然数出现的次数为奇数次。编写程序找出这个自然数。
#include <stdio.h>
#define DIM(a) (sizeof(a)/sizeof(*a))
int main()
{
int a[] = {2,3,5,7,2,2,2,5,3,7,1,1,1};
int find = 0;
int i = 0;
for(i=0;i<DIM(a);i++)
{
find = find ^ a[i];
}
printf("find=%d\n",find);
return 0;
}