位运算符用来对二进制位进行操作。位运算符中,除 ~ 以外,其余均为二元运算符。
操作数只能为整型和字符型数据。
C语言中六种位运算符:
& 按位与
| 按位或
^ 按位异或
~取反
<<左移
>>右移
按位与运算符"&"
只有对应的两个二进位均为1时,结果位才为1 ,否则为0。参与运算的数以补码方式出现。(正数补码就是原码,负数在对应正数的原码上取反+1)
按位或运算符“|”
只要对应的二个二进位有一个为1时,结果位就为1。参与运算的两个数均以补码出现。
按位异或运算符“^”
当两对应的二进位相异时,结果为1。参与运算的两个数均以补码出现。
求反运算符“~”
求反运算符~为单目运算符,具有右结合性。 其功能是对参与运算的数的各二进位按位求反。
左移/右移运算符
左移:左移n位就是乘以2的n次方。 其功能为——左边的运算数的各二进位全部左移若干位,由右边的数指定移动的位数,高位丢弃,低位补0。
右移:右移n位就是除以2的n次方。其功能为——左边的运算数的各二进位全部右移若干位,“>>”右边的数指定移动的位数。
(左移是算术左移/逻辑左移,右移是算术右移)
注:算术右移:最高位填充符号位。正数填充0,负数填充1。
优先级
相同优先级中,按结合性进行结合。大多数运算符结合性是从左到右,只有三个优先级是从右至左结合的,它们是单目运算符、条件运算符、赋值运算符。
常用基本运算符优先级:
指针>单目>双目>三目(条件运算符)>赋值>逗号;
先算术运算,后移位运算,最后位运算(没包括左移右移了);
常用技巧
1、获取int类型最大值
int getMaxInt(){
return (1 << 31) - 1;//2147483647, 由于优先级关系,括号不可省略
}
另一种写法
int getMaxInt(){
return ~(1 << 31);//2147483647
}
2、获取int类型最小值
int getMinInt(){
return 1 << 31;//-2147483648
}
注:int是一个32位的符号数,其中第一位代表符号位。当1<<31时,第一位符号位被置为1 。因此返回负数。
3、乘以2的m次方
int mulTwoPower(int n,int m){//计算n*(2^m)
return n << m;
}
4、除以2的m次方
int divTwoPower(int n,int m){//计算n/(2^m)
return n >> m;
} //负奇数不可用,会移动符号位
5、判断一个数的奇偶性
boolean isOddNumber(int n){
return (n & 1) == 1;
}
6、swap交换两个数
void swap(int *a,int *b){
a ^= b;
b ^= a;
a ^= b;
}
7、取绝对值
int abs(int n){
return (n ^ (n >> 31)) - (n >> 31));
/* n>>31 取得n的符号,若n为正数,n>>31等于0,若n为负数,n>>31等于-1 ;
若n为正数 n^0=n,数不变,若n为负数有n^-1 需要计算n和-1的补码,然后进行异或运算, 结果n变号并且为n的绝对值减1,再减去-1就是绝对值 */
}
相当于模拟了补码到原码的过程,当n是负数的时候,左半部分是每位取反,右半部分是+1;
8、求两数较大值
int max(int a,int b){
return b & ((a-b) >> 31) | a & (~(a-b) >> 31);
/*如果a>=b,(a-b)>>31为0,否则为-1*/
}
9、求两数较小值
int min(int a,int b){
return a & ((a-b) >> 31) | b & (~(a-b) >> 31);
/*如果a>=b,(a-b)>>31为0,否则为-1*/
}
10、求两个整数的平均值
int getAverage(int x, int y){
return (x + y) >> 1;
}