C语言位运算符包括:
& 按位与 | 按位或 ~按位取反 ^ 按位异或 >> 左移 << 右移
位运算符是c语言一部分,而且这部分没有什么难度,但是仔细琢磨还是有点东西要注意的
一、首先对位运算符做些总结:
1、位运算符只能对整形数据(包括字符型数据),不能对浮点数类型操作
2、左移右移运算符右边操作数范围只能是[0,31]
(1) 左操作数必须是整数类型 char和short被隐试转换成int后在操作
(2)右操作数的范围[0,31]
(3)左移运算符规则:高位去掉 低位补0
(4)右移运算符规则:高位补符号位 低位去掉
(5)左移运算符相当于乘以2的N次方,效率要比四则运算符效率高
(6)右移运算符相当于除以2的N次方,效率要比四则运算符效率高
3、位运算符没有短路规则(逻辑运算符有这种规则),所有操作数都会有值
4、位运算符的效率高于四则运算符和逻辑运算符
5、位运算符优先级:四则运算符 < 位运算符 < 逻辑运算符
二、说下几个运算符需要注意的地方:
1、应该避免位运算符、逻辑运算符、四则运算符同时出现在一个表达式中,如果非得出现尽量使用()划分开来,表达运算顺序
2、位运算符结果是整数而不是0或者1,逻辑运算符结果是0或者1
3、位运算符优先级 > 逻辑运算符
三、下面我开始写2个程序测试上面结论 (平台Ubuntu10 gcc编译器)
#include <stdio.h>
int main(void)
{
unsigned char i = 0x01;
unsigned int j = 0x80000000;
unsigned int k = 1;
unsigned int m = 3;
//printf("%d\n",3.14&0x01); //error 因为位操作符只能对整形数操作(char和short自动转换int)
//printf("%d\n",3.14<<1); //error 同上
printf("%d,0x%.8x\n",sizeof(1),1);//4和0x00000001 说明字面量默认数据类型是int
printf("%d\n",k << 2); //1*2^2 = 4
printf("%d\n",1 << 2); //1*2^2 = 4
printf("%d\n",k << 33); //1<<2^(33%32) = 1*2^1=2
printf("%d\n",1 << 33); //0
//通过上面测试,我们发现字面量和定义一个相同数,gcc编译器处理方式不一样
//定义一个数时,进行左移或者右移时,当超过移除位数时,定义的数会进行对最大位数取模处理,然后再进行移位
//而字面量数据时,当超过移除位数时,就是0 其中包括带符号数据
printf("%d\n",k << 255); //1<<2^(255%32) = 1*2^31=0x80000000 = -2^31
printf("%d\n",1 << 255); //0 超过移除位数
printf("%d\n",m >> 1); //3/2^1 = 1或者 0011 >> 1 = 0001 = 1
printf("%d\n",3 >> 1); //3/2^1 = 1或者 0011 >> 1 = 0001 = 1
printf("%d\n",m >> 33); //3/2^(33%32) = 1
printf("%d\n",3 >> 33); //0 超过移除位数
printf("%d\n",m >> 255); //3/2^(255%32) = 0
printf("%d\n",3 >> 255); //0 超过移除位数
printf("%d\n",0x80000000>>33); //0 带符号位数据,同样超过移除位数时,也还是 0
printf("%d\n",0x80000000>>255); //0 带符号位数据,同样超过移除位数时,也还是 0
printf("%d\n",-1 >> 1); //-1 内存值 = FFFF FFFF >> 1 = FFFF FFFF = -1
printf("%d\n", 0x01 << 2 + 3); //+号运算符优先级高于<<所以 0x01 << (2 + 3) = 32
printf("%d\n", 3 << -1); //1 不同编译器,结果不同,gcc = 1,BCC = 0 vs = 很大一个负数(int的最小数)
}
#include <stdio.h>
int main(void)
{
unsigned int i,j,k;
i = 0;
j = 0;
k = 0;
if(++i | ++j & ++k)
{
printf("Run here ...\n");
printf("i = %d\nj = %d\nk = %d\n",i,j,k);//i = 1 j = 1 k = 1
}
i = 0;
j = 0;
k = 0;
if(++i || ++j && ++k)
{
printf("Run here ...\n");
printf("i = %d\nj = %d\nk = %d\n",i,j,k);//i = 1 j = 0 k = 0
}
return 0;
}
通过上面测试,位运算是没有短路规则,而且位运算算出来是一个整数,而不是像逻辑运算符是有短路规则,结果是0或者1