CSAPP-datalab

本文介绍了多个基于位运算的编程题目,包括bitAnd、getByte、logicalShift等,每个题目提供了详细的解题方法和代码实现,涉及位操作如德摩根定理、右移、逻辑非等,并讨论了特定限制条件下的解题策略。

写在前面的话:
这个实验网上已经有很多版本的实现方式了,对于我这个编程菜鸟而言这个实验真的很难,建议大家第一次做的时候先挑软柿子捏,把自己能想出来的先做完后再去想难的,真的想不出来就及时看网上其他人的实现思路。全部做完后隔几天再做一次,相信你能有全新的理解。


1.bitAnd


1.1【题目要求】

/*
bitAnd - 使用 ~ 和 | 实现 x&y
例子:bitAnd(6, 5) = 4
合法操作:~ |
最大操作数:8
难度评级:1
*/

1.2【解题方法】

运用德摩根定理,x&y <==> ~ ((~ x) | (~ y))

1.3 【代码】

int bitAnd(int x, int y) {
   
   
  return ~((~x) | (~y));
}

2.getByte


2.1 【题目要求】

/*
getByte - 从一个字中提取第n个字节
字节从0(LSB)到3(MSB)编号
例子:getByte(0x12345678,1)= 0x56
合法操作:!〜&^ | + << >>
最大操作数:6
难度评级:2
*/

2.2 【解题方法】

先将n扩大8倍,由于不能使用*操作,所以只能用左移3位来代替;
再将x右移n位,这要所要求的那个字节就会来到最后八位,最后再用16进制数0xff与x相与即可;

2.3 【代码】

int getByte(int x, int n) {
   
   
  n<<=3;
  x>>=n;
  return (x & 0xff);
}

3.logicalShift


3.1 【题目要求】

/*
logicalShift - 使用逻辑右移将 x 向右移动 n 位
可假设 0 <= n <= 31
例子:logicalShift(0x87654321,4) = 0x08765432
合法操作:!〜&^ | + << >>
最大操作数:20
难度评级:3
*/

3.2 【解题方法】

逻辑右移是不考虑所输入的数的符号位的,高位自动补0,在这个程序的开头的提示中说,假设所有的右移都为算数右移“2. Performs right shifts arithmetically.”,所以直接使用右移操作符>>会导致结果出错;所以就要对结果进行修正。修正的目的在于将右移后的高n为全部变为零,即我们要构造一个高n位为0低32-n位为1的数与算数右移n位后的x相与再返回最终结果;

3.3 代码

错误示例:

int logicalShift(int x, int n) {
   
   
  int y=(1<<31)>>n;
x>>=n;
  return (x & (~y));
}

在一开始我直接想当然的采取上述方法进行操作,发现结果是错误的,原因在于y再右移的过程中虽然也是移了n位,但是由于本身其第31位就存在一个1,导致右移n位后变成了高n+1位都为1;
例如假设右移三位,则y一开始为0x10000000,右移三位后变为0xf0000000,这就变成了高四位为1,而我们只想要高3位为1,这个时候就要对于y做进一步修正,使其左移1位;

int logicalShift(int x, int n) {
   
   
  int y=(1<<31)>>n;
  y<<=1;
  x>>=n;
  return (x & (~y));
}

而且我发现这个程序很矫情的一个点是,你所有的变量必须在一开始就声明,例如上面函数中的y,如果你不一开始就声明出来他,编译的时候就会报错:
例如:

int logicalShift(int x, int n) {
   
   
  x>>=n;
int y=(1<<31)>>n;
  y<<=1;
  x>>=n;
  return (x & (~y));
}

4.bitCount


4.1 【题目要求】

/*
bitCount - 返回 word 中 1 的个数
例如:bitCount(5) = 2,bitCount(7) = 3
合法操作:! ~ & ^ | + << >>
最大操作数:40
难度等级:4
*/‘

4.2 【解决方案+代码】

int bitCount(int x) {
   
   
  int c,t1,t2,t3,t4,t5;
  t1=0x55|((0x55)<<8);<
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值