CSAPP DataLab

实验环境搭建

参考以下链接

https://zhuanlan.zhihu.com/p/505497911

实验内容

介绍

The purpose of this assignment is to become more familiar with bit-level representations of common patterns, integers, and floating-point numbers. You’ll do this by solving a series of programming “puzzles.”
此任务的目的是更熟悉常见模式、整数和浮点数的位级表示。您将通过解决一系列编程“难题”来实现这一点
我们仅仅需要完成bit.c中的相关函数
每次编写新的代码后重新make

./btest -f 实现的函数

以bitXor为例子
bitXor运行实例

要实现的函数

在这里插入图片描述

  • bitXor
    在这里插入图片描述
    只利用取反和&实现异或操作
    异或的德摩根律是
(x&~y+ ~x&y)

考虑到只能用非和与,所以对上式取反

int bitXor(int x, int y) {
   return ~(~(x&(~y))&(~(y&(~x))));
}

测试结果
在这里插入图片描述

  • tmin
    在这里插入图片描述
    返回最小补码
    以8bit的数字为例,可以表示的范围是-128-127
    127考虑符号位是0111 1111
    -128=-1+ -127
    转换成补码形式的运算可以得到是1000 0000
    因为在补码里面负数的符号位既是符号位也是数值位置
    所以32位机器下最小的补码是1左移31位
int tmin(void) {
  return 1<<31;
}
  • isTmax
    在这里插入图片描述
    返回最大补码
    最大的补即为0x7fffffff
int isTmax(int x) {
  if(x|0x7FFFFFFF==0)
  return 1;
  else return 0;
}
  • allOddBits
    在这里插入图片描述
    判断数值的奇数位是否全是1
    0xAA=1010 1010刚好奇数位置都是1
int allOddBits(int x) {
  int a=0xAAAAAAAA;
  x=x&a;
  x=x^a;
  return !x;
}
  • negate
    返回输入值的负数
    在这里插入图片描述
int negate(int x) {
  return (~x+1);
}
  • isAsciiDigit
    在这里插入图片描述
    判断ASCII编码是否在0-9之间
    代码如下
int isAsciiDigit(int x) {
   int a;
   a=x-0x30;
   a=a>>31;
   int b=0x39-x;
   b=b>>31;
   return !a&!b;
   
}

将负数转换补码形式即可

int isAsciiDigit(int x) {
   int a;
   a=x+(~0x30+1);
   a=a>>31;
   int b=0x39+(~x+1);
   b=b>>31;
   return !a&!b;
}

取符号位进行比较,是否大于0x30和小于0x39

  • conditional
    在这里插入图片描述
    条件运算符,x?y:z
    x=0 ? yes->z
    else y;
    不是
    区别于
if(x) y;
else z;

错误示例

int conditional(int x, int y, int z) {
   
  x=(x>>31)&0x1;//这里取符号位作为判断条件
  return ((~x+1)&z)|(~(~x+1)&y);
}

正确打开方式

int conditional(int x, int y, int z) {
   
  x=!!x;
  return ((~x+1)&y)|(~(~x+1)&z);
}

在CSAPP书中
在这里插入图片描述
当x是0时候,两次!运算得到的结果是0,0按位取反+1是-0,还是0,全部翻转然后&z,即可得出z。
这里这道题困扰了我很久,因为没有清楚知道三元运算符的实际意义。

  • isLessOrEqual
    在这里插入图片描述
    最直接的做法就是这种
    在这里插入图片描述
    但是这种做法存在的问题也很明显就在边界值
    在这里插入图片描述
    存在溢出问题。
    正确打开方式
int isLessOrEqual(int x, int y) {
    int z = (y + ~x + 1) >> 31;
	int a = x >> 31;
	int b = y >> 31;
	int xor1 = a ^ b;
	int result = (~xor1 & z) | (xor1 & b);
	return !result;
}

这里借鉴了别人的做法
取x,y的符号位,如果符号相同就不会存在溢出的问题
如果符号不同,取y的符号位,负数减去正数肯定还是负数,正数减去负数肯定还是正数。

  • logicalNeg
    在这里插入图片描述
    要求:实现!的功能
int logicalNeg(int x) {
  x|=x>>16;
  x|=x>>8;
  x|=x>>4;
  x|=x>>2;
  x|=x>>1;
  return (~x)&0x1;
  
}

思路:将所有位进行或运算

  • howManyBits
    在这里插入图片描述
    要求:返回表示x所需的最小位数二的补码
    12=0x01100 要考虑进符号位
    这道题目我做的时候没有什么好的思路,借鉴了B站上up主的做法。
    b站up主讲解视频
    在这里插入图片描述
    然后这个老哥的思路也不错
    讲解思路
    在这里插入图片描述
    这个作者的代码思路很清晰,在这里谢谢大佬。
    后面的关于浮点数的函数主要考察概念没有什么亮点,so pass。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值