Lab 1
Introduction
The purpose of this assignment is to become more familiar with bit-level representations and manipulations.
You’ll do this by solving a series of programming “puzzles.”
Many of these puzzles are quite artificial, but you’ll find yourself thinking much more about bits in working your way through them.
Coding rules
Replace the “return” statement in each function with one
or more lines of C code that implements the function. Your code
must conform to the following style:
int Funct(arg1, arg2, ...) {
/* brief description of how your implementation works */
int var1 = Expr1;
...
int varM = ExprM;
varJ = ExprJ;
...
varN = ExprN;
return ExprR;
}
-
Each “Expr” is an expression using ONLY the following:
- Integer constants 0 through 255 (0xFF), inclusive. You are
not allowed to use big constants such as 0xffffffff. - Function arguments and local variables (no global variables).
- Unary integer operations ! ~
- Binary integer operations & ^ | + << >>
- Integer constants 0 through 255 (0xFF), inclusive. You are
-
Some of the problems restrict the set of allowed operators even further.
Each “Expr” may consist of multiple operators. You are not restricted to
one operator per line. -
You are expressly forbidden to:
- Use any control constructs such as if, do, while, for, switch, etc.
- Define or use any macros.
- Define any additional functions in this file.
- Call any functions.
- Use any other operations, such as &&, ||, -, or ?:
- Use any form of casting.
You may assume that your machine:
- Uses 2’s complement, 32-bit representations of integers.
- Performs right shifts arithmetically.
- Has unpredictable behavior when shifting an integer by more
than the word size.
EXAMPLES OF ACCEPTABLE CODING STYLE:
/*
* pow2plus1 - returns 2^x + 1, where 0 <= x <= 31
*/
int pow2plus1(int x) {
/* exploit ability of shifts to compute powers of 2 */
return (1 << x) + 1;
}
/*
* pow2plus4 - returns 2^x + 4, where 0 <= x <= 31
*/
int pow2plus4(int x) {
/* exploit ability of shifts to compute powers of 2 */
int result = (1 << x);
result += 4;
return result;
}
Special requires
总结上述规则可以得出以下几点结论:
- ! ˜ & ˆ | + << >> 只有这些操作符允许使用,在特定题目中可能还会有所限制,而且要注意ops的数目
- 不允许使用C语言中的保留字
if, do, while, for, switch
等 - 右移为算术右移,整数均为32-bits
- 需要使用
./dlc
检查是否遵守规则,仔细分析可以发现,声明变量的时候必须连续将所有变量一次性声明完毕,即不能在声明中间掺杂非声明代码,例如以下声明即为非法声明:
int x;
int y;
x = 1;
y = 2;
... //一些非声明的代码
int num;
Puzzle 1
- Requires
/*
* bang - Compute !x without using !
* Examples: bang(3) = 0, bang(0) = 1
* Legal ops: ~ & ^ | + << >>
* Max ops: 12
* Rating: 4
*/
- Analysis
- 分析题意
- 可以看出0为特殊值,所以考虑先判断出来x是否为0,使用
x | -x
,如果x=0,则该值为0,否则符号位必为1 - 之后有两种方式得到正确输出
- 考虑到符号位以及算术右移的特殊性,使用
(x | -x) >> 31
可获得0或-1,然后+1即为正确输出
int bang(int x)
{
return (x | (~x + 1)) >> 31 + 1;
}
- 先取反,符号位变成1或0,右移之后再取最后一位
int bang(int x)
{
return (~(x | (~x + 1)) >> 31) & 1;
}
Tip: -x = ~x + 1
Puzzle 2
- Requires
/*
* bitCount - returns count of number of 1's in word
* Examples: bitCount(5) = 2, bitCount(7) = 3
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 40
* Rating: 4
*/
- Analysis
- 分析题意:就是将给定的十进制数转化为二进制,再数出1的个数
- 如果忽略Max ops: 40的要求的话,这道题非常简单,只需要右移31次,每次将最低位取出来累加即可,代码如下:
int bitCount(