位操作符

位操作运算符

使用位操作符进行运算,都是以二进制补码进行运算

原码 反码 补码

正数

原码反码补码都相同

负数

第一位符号位不变

反码由原码取反

补码:反码+1

原码===》补码,符号位不变,取反+1

补码===》原码,符号位不变,取反+1

按位与 & 同1为1——全是真才是真 (双目运算符)

0&任何数都为0

int n = 10, k = -10;
	n = n & 1;
	k = k & 1;
	printf("n=%d\nk=%d\n", n,k);
	/*n=10
	原码反码补码:0000 0000 0000 0000 0000 0000 0000 1010
	1:          0000 0000 0000 0000 0000 0000 0000 0001
	             0000 0000 0000 0000 0000 0000 0000 0000
	k=-10
	原码:        1000 0000 0000 0000 0000 0000 0000 1010
	反码:        1111 1111 1111 1111 1111 1111 1111 0101

	补码(+1)     1111 1111 1111 1111 1111 1111 1111 0110                            1:                       0000 0000 0000 0000 0000 0000 0000 0001
			     0000 0000 0000 0000 0000 0000 0000 0000
     */

按位或 | 有1为1,没有为0——有一个为真就是真的(双目运算符)

int n = 10, k = -10;
	n = n | 1;
	k = k | 1;
	printf("n=%d\nk=%d\n", n,k);
	/*n=10
	原码反码补码:0000 0000 0000 0000 0000 0000 0000 1010
	1:          0000 0000 0000 0000 0000 0000 0000 0001
	             0000 0000 0000 0000 0000 0000 0000 1011
				  结果是11
	k=-10
	原码:        1000 0000 0000 0000 0000 0000 0000 1010
	反码:        1111 1111 1111 1111 1111 1111 1111 0101

	补码(+1)     1111 1111 1111 1111 1111 1111 1111 0110                            1:          0000 0000 0000 0000 0000 0000 0000 0001
				1111 1111 1111 1111 1111 1111 1111 0111
	因为是负数所以求其补码
	             1000 0000 0000 0000 0000 0000 0000 1000
				1000 0000 0000 0000 0000 0000 0000 1001
     */

按位非 ~ 取反 —— 符号位要参与运算(单目运算符)

int n = 10;
	n = ~n;
	printf("n=%d", n);
	/*
	n=10
	原码反码补码:0000 0000 0000 0000 0000 0000 0000 1010
	取反         1111 1111 1111 1111 1111 1111 1111 0101
	因为是负数所以要求其补码
	             1000 0000 0000 0000 0000 0000 0000 1010
			    1000 0000 0000 0000 0000 0000 0000 1011
    */

按位异或 ^ 同则为0,异则为1——相同为假,不同为真

int n = 10;
	n = n ^ 1;
	printf("n=%d", n);
	/*
	n=10
	原码反码补码:0000 0000 0000 0000 0000 0000 0000 1010
	1:           0000 0000 0000 0000 0000 0000 0000 0001
	             0000 0000 0000 0000 0000 0000 0000 1011
	
	*/

左移 << 向左移动,低位补0(单目运算符)

int n = 10;
	n = n << 1;
	//表示左移1位
	printf("n=%d", n);
	/*
	n=10
	原码反码补码:0000 0000 0000 0000 0000 0000 0000 1010
	左移1位      0000 0000 0000 0000 0000 0000 0001 0100
	 低位补0,高位溢出的舍弃
	 得到n为20
	*/

右移 >> 向右移动,高位补符号(单目运算符)

int n = 10;
	n = n >> 1;
	printf("n=%d", n);
	/*
	n=10
	原码反码补码:0000 0000 0000 0000 0000 0000 0000 1010
	右移1位	  0000 0000 0000 0000 0000 0000 0000 01010
	前面空的补符号位,开始为1就补1,为0就补0
	后面多出的舍弃
	得到n为5
	*/
左移右移如果是负数,就要用它的补码来移动

位运算符的运算效率最高

使用三种方法交换两个变量的值
//第一种方法
	//使用三种方式交换两个变量的值
	int m = 10, n = 30;
	printf("m=%d n=%d\n", m, n);
	int temp;
	temp = m;    //使用中间变量
	m = n;
	n = temp;
	printf("m=%d n=%d\n", m, n);
	//优点;简单,容易理解,直观
	//缺点:要使用第三方变量
	
	//第二种方法
	m = m + n;
	n = m - n;
	m = m - n;
	printf("m=%d n=%d\n", m, n);
	//优点;不使用第三方变量
	//缺点:复杂,数据溢出,会消耗性能

	//第三种方法
	m = m^n;
	n = m^n;
	m = m^n;
	printf("m=%d n=%d\n", m, n);
	//使用了按位异或,位操作符,效率高
	//不适用第三方变量,不会数据溢出

按位异或交换两个变量的值

short n=2,m=3;
	m=m^n;
	n=m^n;
	m=m^n;
	printf("m=%d n=%d",m,n);
	/*这样就能交换两个变量的值,原因:
	 n:0000 0000 0000 0010
	 m:0000 0000 0000 0011
	   0000 0000 0000 0001
	所以m=1
	m:0000 0000 0000 0001
	n:0000 0000 0000 0010
	  0000 0000 0000 0011
	所以n=3
	m:0000 0000 0000 0001
	n:0000 0000 0000 0011
	  0000 0000 0000 0010
	所以m=2
	*/
	
	
	

使用位运算符,写一个表达式,做以下判断,如果是,要求返回true

1.判断一个数是否是2的n次方

int n = 64;
	bool is = !(n&(n - 1));
	printf("is=%d", is);
//如果是,返回的是1,不是返回的是0

2.判断一个数是否是偶数

//转换为二进制(最后一位)
	//奇数为1,偶数为0
	int n = 3;
	bool is = !(n & 1);
	printf("%d", is);
//是偶数输出1,不是偶数输出0

3.判断一个数是否是正数

	//整数没特殊要求,默认int类型
	int a = -10;
	bool is = !(a >> 31);
	printf("%d", is);
	//是正数输出1,负数输出0

类型提升
char a = 'a', b = 'b';
	printf("%d\n", sizeof(a + b));
	//在进行整型计算是,会自动提升类型为int类型
	//输出的结果是4
//作业
char a=0xa5;
unsigned int b=a>>4+1;
printf("b=%d\n",b);

char a=-0xa5;
unsigned int b=a>>4+1;
printf("b=%d\n",b);

unsigned char a=0xa5;
int b=a>>4+1;
printf("b=%d\n",b);






posted @ 2020-11-13 20:34  kisfly  阅读(76)  评论(0编辑  收藏  举报