最近在读csapp,做课后实验,但我几乎没用过linux,从实验一就完全不知道怎么运行测试C代码。为了帮助和我一样的小白(可能没有哈哈哈),于是从这篇文章开始记录自己做lab实验的一些细节。
(系统为32位,即每个数字可表示8位的二进制)
一、环境搭建步骤
1、安装docker,在docker上创建ubuntu镜像容器,参考链接1;
2、参考链接1里的本地文件夹共享部分我没成功,参照链接2成功实现共享,参考链接2;
3、创建好容器后,在容器中完成参考链接1中的几个apt命令,还有sudo apt-get install make;
4、在容器中进入共享文件夹,直到“datalab-handout”这一层,就可以开始做实验啦!
二、习题思路与题解
1. bitXor
题目:实现x与y之间的异或运算,可用符号为~,&
思路:
x⊕y= (¬x∧y)∨(x∧¬y)=¬(¬x∧¬y)∧¬(x∧y),用文氏图比较好理解,图中两个圈分别表示x与y,异或的结果是红色的部分,既不属于两个圆外部的白色(¬x∧¬y),也不属于两个圆相交的白色(x∧y),而是剩下的部分。
int bitXor(int x, int y) {
return (~(~x&~y))&(~(x&y));
}
使用C语言编辑器改完bits.c文件里的函数,使用以下2条命令测试单个函数是否正确
注意:每次修改完代码再重新测试时,都要运行make btest
2. tmin
题目:二进制补码表示的最小值
思路:32位系统的编码是8位的16进制,16进制每一位转化到二进制又占四个位,即1000000000000000,最高位权重为-2^15,其余位的权重都是正数。1的补码表示是0000000000000001,向左移动31位,后面全补0,就能得到最小值。
int tmin(void) {
return 1<<31;
}
3. int isTmax(int x)
题目:若x是二进制补码能够表示的最大值,返回1,否则返回0
思路:最大值是0x7FFFFFFF,观察到x取该值时x+1为0x80000000,x^~(x+1)刚好为0(每个数和自身的异或都为0),可以return !(~(x+1)^x)
。但有个特殊情况0xFFFFFFFF(十进制的-1),它代入上式的返回值也是1,要特殊处理,故在后面加上&!!(x+1)
,这里我一开始还在纠结为什么要2个感叹号,原因是需要把所有非零的数都转化为1。
int isTmax(int x) {
return !(~(x+1)^x)&!!(x+1);
}
4. int allOddBits(int x)
题目:从第0到第31位,若所有奇数位的值都是1,则返回1
思路:所有奇数位都为1的数是0xAAAAAAAA,令其为temp,x&temp会使得偶数位全为0,若x本身的奇数位全为1,则x&temp会与temp相同,用异或来判断即可
int allOddBits(int x) {
int temp=0xAAAAAAAA;
return !((x&temp)^temp);
}
5. int negate(int x)
题目:获得x的负数
思路:~x+x=-1
(所有位均为1),-x+x=0
,故-x=~x+1
int negate(int x) {
return ~x+1;
}
6. int isAsciiDigit(int x)
题目:
思路:
在这里插入代码片
7. int conditional(int x, int y, int z)
题目:
思路:
在这里插入代码片
8. int isLessOrEqual(int x, int y)
题目:
思路:
在这里插入代码片
9. int logicalNeg(int x)
题目:
思路:
在这里插入代码片
10. int howManyBits(int x)
题目:
思路:
在这里插入代码片
11. unsigned floatScale2(unsigned uf)
题目:
思路:
在这里插入代码片
12. int floatFloat2Int(unsigned uf)
题目:
思路:
在这里插入代码片
13. unsigned floatPower2(int x)
题目:
思路:
在这里插入代码片