运算符&和&&以及|和||的区别
& 按位与操作
- & 左右两侧可以是操作数也可以是布尔表达式
- 1&0=0; 8&28=01000&11100=01000=8;
- & 左右两侧表达式都会进行计算
&& 短路运算符
- &&执行时先计算左侧再计算右侧,如果左侧是false,那么右侧就不再计算。
- 在遇到判断语句的时候,使用&&的效率更高。
- &&左右两侧只能是布尔表达式
|与||
- |与||同&、&&类似
- &&和||称为短路运算符
位运算(&、|、^、~、>>、<<)
位运算概述
计算机中在进行四则运算(+、-、*、/)时,背后原理均为位运算(&、|、^、~、>>、<<)
- &:与、两位均为1时,结果才为1
- |:或、两位均为0时,结果才为0
- ^:异或、两位相同为0,相异为1
- ~:取反、0变1,1变0
- <<:左移、各二进位全部左移若干位,高位丢弃,低位补0
- >>:右移、各二进位全部右移若干位,高位补0,有符号数,各编译器处理方法不同,有的补符号位,有的补0。
按位与运算&
负数按照其补码形式参加按位与运算。
与运算的用途:
- 1.清零:将一个单元清零,只要与一个各位都为零的数值相与,结果为0。
- 2.取一个数的指定位:若要取X的低四位,只需找出另一个数Y,使得Y低四位为1,其余位为0,X与Y相与即为X的低四位。
- 3.判断奇偶:根据最末位是0还是1来决定,为0就是偶数,为1就是奇数。因此可以用if ((a & 1) == 0)代替if (a % 2 == 0)来判断a是不是偶数。
按位或运算 |
负数按照其补码形式参加按位或运算。
或运算的用途:
- 1.对一个数据的某些位设置为1:与按位与运算取一个数的指定位类似
异或运算 ^
运算规则:0^0=0, 0^1=1, 1^0=1, 1^1=0 (即相同等于0,不同等于1)
异或运算满足的规则:
- 1.异或运算满足交换律和结合律
- 2.对任何数x都有x^x=0, x^0=x(自身异或自身为0,自身与0异或为自身)
- 3.自反性:abb=a^0=a;
异或运算的用途:
- 1.反转指定位:与1进行异或即可反转
- 2.与0异或值不变
- 3.交换两个数(不引入第三变量)
void Swap(int &a, int &b){
if (a != b){
a ^= b;//a=a^b
b ^= a;//b=b^a
a ^= b;//a=a^b
}
}
## 取反运算符~ > 取反运算的用途: - 1.使一个数的最低位为0:a&~1
需要注意的是:“~”运算符的优先级比算术运算符、关系运算符、逻辑运算符和其他运算符都要高。
运算符优先级:
- 第一级:圆括号【()】、下标运bai算符【[]】、分量运算符的指向结构体成员运算符【->】、结构体成员运算符【.】。
- 第二级:逻辑非运算符【!】、按位取反运算符【~】、自增自减运算符【++ --】、负号运算符【-】、类型转换运算符【(类型)】、指针运算符和取地址运算符【*和&】、长度运算符【sizeof】。
- 第三级:乘法运算符【*】、除法运算符【/】、取余运算符【%】。
- 第四级:加法运算符【+】、减法运算符【-】。
- 第五级:左移动运算符【<<】、右移动运算符【>>】。
- 第六级:关系运算符【< > <= >= 】。
- 第七级:等于运算符【==】、不等于运算符【!=】。
- 第八级:按位与运算符【&】。
- 第九级:按位异或运算符【^】。
- 第十级:按位或运算符【|】。
- 第十一级:逻辑与运算符【&&】。
- 第十二级:逻辑或运算符【||】。
- 第十三级:条件运算符【?:】。
- 第十四级:赋值运算符【= += -= *= /= %= >>= <<.= &= |= ^=】。
- 第十五级:逗号运算符【,】。
左移运算符<<
定义:将一个运算对象的各二进制位全部左移若干位(左边的二进制位丢弃,右边补零)
注意:若左移时舍弃的高位不包含1,则每左移一位,相当于该数乘以2
右移运算符>>
定义:将一个数的各二进制位全部右移若干位,正数左补0,负数左补1,右边丢弃。
复合赋值运算符
定义:位运算符和赋值运算符结合,组成新的复合赋值运算符
- &= 例:a&=b 相当于 a=a&b
- |= 例:a|=b 相当于 a=a|b
- >>= 例:a>>=b 相当于 a=a>>b
- <<= 例:a<<=b 相当于 a=a<<b
- ^= 例:a^=b 相当于 a=a^b
位运算符运用汇总--参考链接
/* -------------判断整数x是奇数还是偶数------------- */
/* 1、常规做法:看除以2的余数 */
if (0 == x % 2)
偶数
else
奇数
/*2、 使用位运算 */
if (0 == x & 1)
偶数
else
奇数
/* -------------把r、g、b混合成32位颜色------------- */
#define MAP_RGB(r, g, b) (((r) << 16) + ((g) << 8) + (b))
#define PIXEL_GET_R(pix) (((pix) & 0xFF0000) >> 16)
#define PIXEL_GET_G(pix) (((pix) & 0xFF00) >> 8)
#define PIXEL_GET_B(pix) (((pix) & 0xFF))
/* -------------取整数a的第k位(k=0,1,2,..len(str(a)))------------- */
int b = a >> k & 1;
/* -------------将整数a的第k位清0------------- */
a = a & ~(1 << k);
/* -------------将整数a的第k位置1------------- */
a = a | (1 << k);
/* -------------int型变量循环左移k次------------- */
a=a<<k|a>>16-k (设sizeof(int)=16)
/* ------------- int型变量a循环右移k次------------- */
a=a<<k|a>>16-k; // (设sizeof(int)=16)
a=a>>k|a<<16-k; // (设sizeof(int)=16)
/* ------------- 返回X,Y 的平均值------------- */
int average(int x, int y)
{
return (x&y)+((x^y)>>1);
}
/* ------------- 对于一个数 x >= 0,判断是不是2的幂------------- */
boolean power2(int x)
{
return ((x&(x-1))==0)&&(x!=0);
}
/* ------------- 不用临时变量,交换两个数------------- */
void swap(int x , int y)
{
x ^= y;
y ^= x;
x ^= y;
}
/* ------------- 计算绝对值------------- */
int abs( int x )
{
int y ;
y = x >> 31 ;
return (x^y)-y ; //or: (x+y)^y
}
/* ------------- 取模运算转化成位运算 (在不产生溢出的情况下)------------- */
a % (2^n) 等价于 a & (2^n - 1)
/* ------------- 乘法运算转化成位运算 (在不产生溢出的情况下)------------- */
a * (2^n) 等价于 a<< n
/* ------------- 除法运算转化成位运算 (在不产生溢出的情况下)------------- */
a / (2^n) 等价于 a>> n
例: 12/8 == 12>>3
/* ------------- 乘法运算转化成位运算 (在不产生溢出的情况下)------------- */
a * (2^n) 等价于 a<< n
if (x == a) x= b;
else x= a; 等价于 x= a ^ b ^ x;
x 的 相反数 表示为 (~x+1)
注意
不同长度的数据进行位运算:如果两个不同长度的数据进行位运算时,系统会将二者按右端对齐,然后进行位运算。
以“与运算”为例说明如下:我们知道在C语言中long型占4个字节,int型占2个字节,如果一个long型数据与一个int型数据进行“与运算“,右端对齐后,左边不足的位依下面三种情况补足,
1)如果整型数据为正数,左边补16个0。
2)如果整型数据为负数,左边补16个1。
3)如果整形数据为无符号数,左边也补16个0。
如:long a=123;int b=1;计算a& b。
如:long a=123;int b=-1;计算a& b。
如:long a=123;unsigned intb=1;计算a & b。