第一周任务总结(位运算)

**

位运算

**
位运算的基本知识

  • c语言可以按二进制位进行计算,它只适用于整型或字符型数据
  • 位运算用补码进行运算,正数的补码就是原码,负数的补码为原码取反加1;计算得出的结果如果是正数,就直接等于补码,若是负数则需减1取反,取反时符号位不变。

位运算的运算符
位运算的运算符有以下6种:
1 - 按位与(&):位与运算符“&”是双目运算符

  • 与运算的规则是:只有当对应的两个二进制位都为1时,运算结果中该位才是1,否则,该位是0.
  • 例如,求7&5,7的二进制数为00000111,5的二进制数为00000101;
    7的二进制 00000111
    5的二进制 00000101
    最终结果为00000010
  • 用途:按位与运算通常用于二进制取位操作,例如一个数&1的结果就是取二进制的最末位。这可以用来判断一个整数的奇偶,二进制的最末位为0表示该数为偶数,最末位为1表示该数为奇数

2.按位或(|):位或运算符“|”是双目运算符

  • 或运算的规则是:只有当对应的两个二进制位都为0时,运算结果中该位才是0,否则,该位是1。
  • 例如:求13|21
    13的二进制为00001101
    21的二进制为00010101
    最终的结果为 00011101
    用途:一个数 | 1的结果就是把二进制最末位强行变成1。如果需要把二进制最末位变成0,对这个数 | 1之后再减一就可以了,按位或运算常用来对一个数据的某些位定值为1

3.按位异或(^):异或运算符“ ^ ”是双目运算符

  • 异或运算的规则是:只有当对应的两个二进制位不同时,运算结果中该位才是1,否则,该位是0,即相同为0,不同为1.
  • 例如:求13^12
    13的二进制为00001101
    21的二进制为00010101
    最终的结果为 00011000
  • 用途:异或运算可以用来使操作数的某些位翻转(方法是将该位和1进行异或运算),或者保留某些位(方法是将该位和0进行异或运算)

4.位反运算符(~):位反运算符“ ~”是单目运算符

  • 位反的运算规则是:将所有操作数按位取反,包括符号位(如果是负数减1取反,则取反时符号位不变),即0变成1,1变成0;

  • 例如:求~13
    13的二进制为00001101
    取反后结果为 11110010


5.位左移运算符(<<):位左移运算符“<<”是双目运算符

  • 使用格式: 操作数<<位数
  • 功能是:将一个操作数按指定的位数左移,左移时,从左边移出的高位部分被丢弃,右边空出的低位部分补0;
  • 例如:a=3;
    b=a<<1;计算结果为b=6;
    b=a<<2;计算结果为b=12;
    由此也可得出,左移一位,相当于该数乘以2,左移n位,相当于该数乘以2n

6.位右移运算符(>>):位右移运算符“>>”是双目运算符

  • 使用格式:操作数>>位数

  • 功能是:将一个操作数按指定的位数右移,右移时,从右边移出的高位部分被丢弃,左边空出的高位部分补0还是补1,按下面的规则处理
    1.若操作数是无符号的,右移时,高位补0;
    2.若操作数是有符号的,右移时,在高位补符号位,即正数补0,负数补1 例

  • 如:a=9;
    b=a>>1;计算结果为b=4;
    b=a>>2,计算结果为b=2;
    由此也可得出,右移一位,相当于该数除以2,右移n位,相当于该数除以2n


    纸质月考核后半段关于位运算的例题:

#include <stdio.h>
int main()
{
	int a = 10, b = -25;
	int c = 0, d = 3;
	int e = 20;
 	printf("%d\n", (a << 2));				//  1
 	printf("%d\n", (b >> 3));				//  2
 	printf("%d\n", (b = c));				//  3
 	printf("%d\n", (a & b));				//  4
 	printf("%d\n", (a ^ b));				//  5
 	printf("%d\n", (a | b));				//  6
 	printf("%d\n", (~b));					//  7
 	printf("%d\n", (b >>= 3));				//  8
 	printf("%d\n", (a <= b <= c));				//  9
 	printf("%d\n", (b >> a - 4));				//  10
 	printf("%d\n", (a & 0x1 == b & 0x1));			//  11
 	printf("%d\n", (a | b << ++a > b));			//  12
 	printf("%d\n", (! ~ b++));				//  13
 	printf("%d\n", (a - b, c += d, e - c));			//  14
 	printf("%d\n", (a <<=3 > 0));				//  15
 	printf("%d\n", (a <<= d > 20 ? b && c++ : d--));	//  16
 	return 0;
}

题解
1.(a<<2)
a的二进制数为00001010,使a左移两位00 001010(00),删除左边两位,在右边空出的两位补0,最后答案为40


2.(b>>3)
b的二进制数为11100111,使b右移两位(111)11100 111 删除右边的三位,在左边空出的三位补1,因为原数带符号,所以补1,最后答案为-4


3.(b=c)
对b赋值为c,b=0


4.(a & b)
a的二进制数为00001010
b的二进制数为00000000
答案--------------00000000
为0


5.(a ^ b)
a的二进制数为00001010
b的二进制数为10000000
答案--------------10001010
为10


6.(a | b)
a的二进制数为00001010
b的二进制数为00000000
答案-------------00001010
为10
可以看出,任何数 & 0结果都为0,任何数^0都为它本身,任何数 | 0都为它本身


7.(~b)
b的二进制数为00,取反时符号位也要取反所以变为11,答案是-1.


8.(b>>=3)
b=b>>3,>>的优先级先于=

所以先计算右移三位,(000)011
答案为0,再将此值赋给b,得到最终答案0


9.(a<=b<=c)
从左到右的顺序开始判断a<=b,a=10>b,所以此语句为假,0<c,所以后半句语句为真,返回1,所以最终答案为1


10.(b>>a-4)
-的优先级在>>前
所以先计算a-4=6,再让b>>6,
b的值为0,右移三位结果仍未0


11.(a&0x1== b&0x1)
0x1是指十六进制中的1, == 的优先级在&前,
所以 a&0x1== b&0x1 等价于a&(1==b)&1
b!=0,所以括号内条件为假(0),最终整个式子变为a&0&1,结果为0


12.(a | b << ++a > b)
++先于<<先于>先于|
所以由a | b << 11 > b(a | b << (++a )> b)
变为 a|0>b (a | (b << 11 )> b)
变为 a|0 ,
最终结果为11


13.(!~b++)
++先于~先于!
所以先计算!~ 1,(!~(b++)),
变为 !-2, ( ! (~1));
结果为0
1按位取反的结果为1111 1111 1111 1110;以1开头说明是个负数,该数按位取反在加一得到的结果 2 在加上负号就是-2


14.(a-b , c+=d , e-c)
逗号运算符从左向右依次计算,最终值取最右边的式子
(a-b,c+=d,e-c)
(10 ,c = 3 , 17)
整个式子最终答案取17,但c同时也被赋值为3


15.(a<<=3>=0)
">=“先于”<<="
所以先计算3>=0,答案为1,
再计算a<<=1,a<<=1同为a=a<<1,
a的二进制为00001011,左移一位,0 0001011(0),
结果为22


16.(a<<=d>20?b&&c++:d–)
++,-- 先于>先于 && 先于 ?:先于 <<=
首先计算出(a <<= d > 20 ? b && 3 : 3)
然后(a <<=( d > 20) ? b &&3 : 3)
之后(a <<=0 ?( b &&3) : 3)
再然后(a <<=(0 ?0 : 3))
最后(a <<=3)
a的二进制为00010110,左移三位,000 10110000
结果为176.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值