CSAPP(CMU 15-213):Lab1 DataLab详解(上)

前言

本系列文章意在记录答主学习CSAPP Lab的过程,也旨在可以帮助后人一二,欢迎大家指正!


一、 bitXor()

本函数限制只能使用~和&来完成x^y,即异或运算。
/* 
 * bitXor - x^y using only ~ and & 
 *   Example: bitXor(4, 5) = 1
 *   Legal ops: ~ &
 *   Max ops: 14
 *   Rating: 1
 */
int bitXor(int x, int y) {
  //return ~(~x&~y)&~(x&y);
	  return ~(~(~x&y)&~(x&~y));
}
其中实现的逻辑比较简单,学习过离散数学的都知道,使用德摩根律即可。

二、tmin()

返回最小的补数,通过这道例题来深入理解补数的定义。
/* 
 * tmin - return minimum two's complement integer 
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 4
 *   Rating: 1
 */
int tmin(void) {
  return 1 << 31;

}

三、isTmax()

找出补数形式的最大值
/*
 * isTmax - returns 1 if x is the maximum, two's complement number,
 *     and 0 otherwise 
 *   Legal ops: ! ~ & ^ | +
 *   Max ops: 10
 *   Rating: 1
 */
int isTmax(int x) {
	//return x == ~(1 << 31);  //illegal operator  ==  <<
	return !(x ^ ~(x+1))&!!(x+1);  // -1 is a special case / exception
}

思路
我在做的时候,先将其真实值写出来,然后分析其特征。

对于四位数而言0111就是最大补数,会发现此数+1取反就会变回自身,所以我们只要判断变化后是否与原来相同就好了。

但不能使用==,那么问题又进展到了如何用位运算来表示==

CSAPP中有一道练习题就是此问,我们观察异或运算就可得知,同位的数相同若则为0 ,所以逻辑运算x == y可以表示为!(x^y),不理解的童鞋可以算一下哦~

但这道题还没完!!!!我们这种思路还有一个小小的bug。。。。

对于-11111来说,也符合我们上面的做法,所以要在最后的结果中排除此特殊情况。

这边排除的时候有一个小的技巧,用逻辑判断!!两次非,就可以将-1去除掉啦!

四、allOddBits()

若二进制数字串中奇数位都为1的话,就令其返回1。
/* 
 * allOddBits - return 1 if all odd-numbered bits in word set to 1
 *   where bits are numbered from 0 (least significant) to 31 (most significant)
 *   Examples allOddBits(0xFFFFFFFD) = 0, allOddBits(0xAAAAAAAA) = 1
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 12
 *   Rating: 2
 */
int allOddBits(int x) {
  //return !(0xAAAAAAAA & x ^ 0xAAAAAAAA);  //illegal constant 0xAAAAAAAA
	
	int a = 0xAA;
	int b = (a << 8) | a;
	int c = (b << 16) | b;  // c == 0xAAAAAAAA
	return !((c&x) ^ c);
}

思路
题目中给的例子已经有提示了!! A = 1010这不就是天然的奇数位为1的最好情况吗!

然后我们就可以通过这个天然的标杆来判断了,岂不是很棒!

但因为题目中限制不能直接给常数,所以我们只能通过|的方式来不断拓展A的长度,形成0xAAAAAAAA

之后我们只要通过c&x将x中偶数位为1的清洗为0,然后判断其与0xAAAAAAAA是否相同就好了

五、negate()

返回其相反数
/* 
 * negate - return -x 
 *   Example: negate(1) = -1.
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 5
 *   Rating: 2
 */
int negate(int x) {
  return ~x+1;
}

这个题目比较简单,就不细说了,只要了解数字几种形式基本转化方式的都知道。

六、 isAsciiDigit()

确定x是否在某一范围内
/* 
 * isAsciiDigit - return 1 if 0x30 <= x <= 0x39 (ASCII codes for characters '0' to '9')
 *   Example: isAsciiDigit(0x35) = 1.
 *            isAsciiDigit(0x3a) = 0.
 *            isAsciiDigit(0x05) = 0.
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 15
 *   Rating: 3
 */
int isAsciiDigit(int x) {     // my operator is very complex   my_pos = Max_ops = 15
	int x1 = 0x30;
	int x2 = 0x39;
	int a = x + (~x1+1);
	int b = x2 + (~x+1);
	int test = 1 << 31;
	//return !(test & a) && !(test & b);  //illegal operator  &&
  return !(!!(test & a) + !!(test & b));
}

思路
本题我用了最朴素的想法,通过x与上下限相加减所得的数与零的关系来确定是否在些区间内

通过a & (1 << 31)来判断正负数。

七、conditional()

模拟实现c语言中的三目表达式   ?  :  
/* 
 * conditional - same as x ? y : z 
 *   Example: conditional(2,4,5) = 4
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 16
 *   Rating: 3
 */
int conditional(int x, int y, int z) {
	int a = !!(x^0);     //logic   -->    number
	x = ~a+1;   //a == 1  x = 0xFFFFFFFF   a == 0  x = 0x00000000
  return (x & y) + ((~x) & z);
}

思路
既然是通过x的值来判断返回y还是z,那就可直接得出 return (x & y) + ((~x) & z);

然后只需通过逻辑表达式与一些小操作将x转换为0xFFFFFFFF或者0x00000000即可。

后面的几个函数实现涉及到太多的tricky了,准备暂时先行跳过,先完成最最重要的知识学习!

  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值