实验目的:
1.替换bits.c中各个函数中的return,格式要求如下所示:
int Funct(arg1, arg2, …) {
/* brief description of how your implementation works */
int var1 = Expr1;
…
int varM = ExprM;
varJ = ExprJ;
...
varN = ExprN;
return ExprR;
}
其中,每一个“Expr”只能使用如下规则:
① 数字只能使用0到255(0xff),不能使用像0xffffffff这样大的数字
② 函数参数和局部变量(没有全局变量)
③ 一元运算目:! ~
④ 二元运算目:& ^ | + << >>
2.bits.c中所给的15个函数都是缺失的,需要用上每个函数被允许的操作去实现所要求的功能。
3.下面的操作不被允许:
① 使用任何控制结构,如if, do, while, for, switch等。
② 定义或使用任何宏。
③ 在此文件中定义任何其他函数。
④ 调用任何库函数。
⑤ 使用任何其他的操作,如&&, ||, -, or ?:
⑥ 使用任何形式的casting
⑦ 使用除int以外的任何数据类型。这意味着你不能使用数组、结构等。
对于需要你执行浮点运算的问题,编码规则较不严格。允许使用循环和条件控制也可以同时使用int和unsigned。可以使用任意整数和无符号常量。
实验内容及操作步骤:
一、初步安装dlc:
由于第二次试验是基于dlc编译环境,所以需要先进行添加,即将本次实验的文件夹datalab-handout复制到linux环境下,之后的实验都是在这个文件夹下进行:
二、填写bits.c中实验需填写的内容,并进行简单的解释:
先对整个bits.c文件进行翻译,了解到要求是:
警告:请不要使用<stdio.h>头文件,他会使dlc编译器发生错误,你可以仍旧在不包含<stdio.h>头文件的情况下使用printf语句来调试,尽管你可能会有警告信息。一般情况,忽视警告信息是不对的,但在这里没有问题
你将会通过编译和调用在这个源文件中的函数来设计自己的代码,并最终向数据实验室提供你的解决方案。通过一行或多行的c语言代码来替代函数中的return语句并实现函数,你的代码必须满足下面几个规则:
- 0到255(包含)之间的整数常量,你不能使用太大的常数
- 功能语句和局部变量(不能使全局变量)
- 一元整数操作如!(逻辑非)和~(按位非)
- 二元整数操作如&(按位与)、^(异或)、|(或)、+(相加)、<<(算术左移)、>>(算术右移)
你不被允许以下操作: - 使用任何一个控制结构,像if,do,while,for,switch等等
- 定义或使用宏
- 在本文件中定义任何一个格外的函数
- 声明或调用任何函数
- 使用别的任何操作符,如&&、||、-或者?
- 使用任何形式的指针
- 使用任何除了int之外的数据类型,这里暗示你不能使用数组,结构体和类
你可以假定你的机器: - 使用2的补码表示负数,32位表示整数
- 执行算术右移
- 移动一个整数超过他的字长的时候会产生不可预测的后果
对于要执行浮点操作的问题,编码规则不那么严格,允许使用循环和条件控制即if和for语句,你可以使用int和unsigned,可以使用任意整数和无符号常量
你被禁止: - 定义或使用宏
- 在本文件中定义任何其他函数
- 声明或调用任何函数
- 使用任何形式的指针
5.使用除int和无符号以外的任何数据类型,意味着不能用数组,结构体或类 - 使用任何浮点数据类型,操作或常量
提示: - 使用dlc(数据实验室检查器)编译器(在讲义中描述)来检查解决方案的合法性
- 每一个函数都有一个最大数量的操作符,允许你在实现该函数时使用这些操作符。最大操作符计数由dlc检查,请注意“=”不计算在内,你可以随意使用运算符
- 使用btest测试工具来检查你的功能是否正确
- 使用bdd检查器正式的验证你的功能
- 每个函数的最大操作数在每个函数的头注释中给出,如果在编写和次文件中最大操作数之间存在不一致,请将此文件作为权威来源
三、对函数进行添加和重写:
1、
/*
* bitAnd - x&y using only ~ and |
* Example: bitAnd(6, 5) = 4
* Legal ops: ~ |
* Max ops: 8
* Rating: 1
*/
int bitAnd(int x, int y) {
return ~((~x)|(~y));
}
代码解释:使用~与|实现按位与,真值表为(每一位):
由于最高限制次数为8次,那么只能使用德摩根律,得到x&y=(X|~Y)即可。
2、
/*
* getByte - Extract byte n from word x
* Bytes numbered from 0 (LSB) to 3 (MSB)
* Examples: getByte(0x12345678,1) = 0x56
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 6
* Rating: 2
*/
int getByte(int x, int n) {
return ((x>>(n<<3))&0xff);
}
代码解释:将一个32位数实现返回对应编号位置的数字,先将编号n转换为移动的位数,比如2就要移动2x2^3个位置,0则不需要移动,将所需要的数字移动到最低位,接着按位与0XFF,只取最低的两位,得到最终结果。按位与0xFF表示保留最后一个字节。
例:假设x=0x12345678,n=2
那么78是编号0,56编号为1,n移动3位后得到的结果是2x8=16位,即需要把x向右移动16位,算数逻辑均可。以算数为例,则x为0x00001234,取最后的两位即34,即为所求结果。
3、
/*
* logicalShift - shift x to the right by n, using a logical shift
* Can assume that 0 <= n <= 31
* Examples: logicalShift(0x87654321,4) = 0x08765432
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 20
* Rating: 3
*/
int logicalShift(int x, int n) {
return ~((((1<<31)&x)>>n)<<1)&(x>>n);
}