C语言中的位运算符:
&按位与,|按位或,^按位异或,~取反,<<左移,>>右移。
2&3 010&011->010->2
结合律 a&b&c==(a&b)&c==a&(b&c)
交换律 a&b==b&a
<<左移规则:高位丢弃,低位补0
>>右移规则:高位补符号位,低位丢弃
1<<2 001->100->4
8>>3 1000->0001->1
~8 1000->0111->7
0x1<<2+3的结果?
0x1<<(2+3),数学运算符的优先级高于位运算符
防错准则:
避免运算符,逻辑运算符和数学运算符同时出现在一个表达式中。C语言有自己的优先级,这和平时数学中的常识不符合,容易出错。
当运算符,逻辑运算符和数学运算符同时出现在一个表达式中,多用括号()明确运算顺序。
右移n位,相当于除以2的n次方,但是效率比数学运算高。
交换两个变量的值的3种方法:
#define Swap(a,b) \
{ \
int temp=a; \
a=b; \
b=temp; \
}
//需要引入一个临时变量,占用额外空间;适合任何数。
#define Swap(a,b) \
{ \
a=a+b; \
b=a-b; \
a=a-b; \
}
//注意int的范围,当a很大,b很大时可能会溢出,结果出错。
#define Swap(a,b) \
{ \
a=a^b; \
b=a^b; \
a=a^b; \
}
//不会溢出,效率高;但是适用整数,不适用于浮点数。
面试题:一个数列,其中的每个数都是自然数且都以偶数次出现,仅有一个例外,请编程找出这个出现奇数次的数。
例如:2,,3,5,7,2,2,2,5,3,7,1,1,1
思路一:1.排序数组,2遍历数组并计数,找出奇数次的数。(排序耗时)。
思路二:1.找出数组最大值max,2.动态申请max+1大小的数组b,并清零
3.用数组b对原始数据进行统计,4.遍历数组b找出奇数,得到对应的值。(空间换时间,耗空间)
思路三:2^3^5^7^2^2^2^5^7^1^1^1^1 --->1 交换律和结合律(不耗时,空间小)
#define NUM(a) (sizeof(a)/size(*a))
int a[]={2,3,5,7,2,2,2,3,5,7,1,1,1};
int find=0;
int i=0;
for(i-0;i<NUM(a);i++)
{
find=find^a[i];
}
printf(“%d\n”,find);
思考题:
1.&&,||与&,|,~的意义是否相同?他们可以在条件表达式中交替使用吗?为什么?
2.1<<32的结果是什么?1<<-1的结果是什么?为什么?