CSAPP LAB
丑话说在前头 不做不知道 一做吓一跳 是真的什么都不知道捏~
当然了还是和书中建议一般:
Don't cheat, even the act of searching is checting.
yub刚开始想整tmux玩https://www.jikecloud.net/supports/docs/tmux-intro/ 发现字体颜色太暗了眼睛要麻了(懒得调)最后还是去了terminal
Data Lab
bitXor(x,y)
只使用两种位运算实现异或操作.
^(异或)相异为1不用为0
~ 非 也就是按位取反
& 逻辑与 补码同为1才为1 其余为0
有点好笑的是yub刚开始忘记负数这茬了,没过脑子很简单的,haha 玉玉了
/*
* 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;
}//正数范围满足
只要分别计算 不同为0和不同为1的情况即可 也就是:
/*
* 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);
}
也可以简写成
(x & y) | (~x & y)
tmin()
使用位运算获取对2补码的最小
int
值.
说实话这个英语底子还是得加强哈 扫一遍题目yub以为是return两个数中最小的那个(怎么看也是有逻辑错位u 两个数不应该是较小的吗…)
/*
* tmin - return minimum two's complement integer
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 4
* Rating: 1
*/
int tmin(void){
return 0x1<<31;
}
C语言中int是整型,4bytes32位,根据补码变形为负数即可.
isTmax(x)
通过位运算计算是否是补码最大值.
给出允许可以使用^且前面已经求出了tmin yub觉得这下好办
/*
* 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) {
!(~((x + 1) + x) | !(x + 1));
}
后看了其他笔者的解法,yub感觉思维又缜密了一些~
/*
* 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) {
int i = x+1;//Tmin,1000...
x=x+i;//-1,1111...
x=~x;//0,0000...
i=!i;//exclude x=0xffff...
x=x+i;//exclude x=0xffff...
return !x;
}
思路
前提:必须知道补码最大值是多少.(针对 int
类型),最大值当然是符号位为 0,其余全是 1.
在此说一下个人理解,最终返回值为 0 或 1,要想判断给定数 x
是不是补码最大值(0x0111,1111,1111,1111
),则需要将给定值 x
向全 0 值转换判断,因为非 0 布尔值就是 1,不管你是 1 还是 2。根据我标注的代码注释理解,如果 x
是最大值,将其转换为全 0 有很多方法,不过最终要排除转换过程中其他的数值,比如本例子中需要排除 0xffffffffffffffff
的情况:将 x 加 1 的值再和 x 相加,得到了全 1(函数第二行),然后取反得到全 0,因为补码 - 1 也有这个特点,所以要排除,假设 x 是 -1,则 +1 后为全 0,否则不为全 0,函数 4-5 行则是排除这种情况。
allOddBits(x)
判断所有奇数位是否都为 1,这里的奇数指的是位的阶级是 2 的几次幂。重在思考转换规律,如何转换为对应的布尔值。
“(位)掩码”o.0? yub觉得是知识盲区一样 https://blog.csdn.net/qq_20233867/article/details/73743351
https://blog.csdn.net/u013279723/article/details/107447260
/*
* 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) {
int odd = (0xAA << 24) + (0xAA << 16) + (0xAA << 8) + 0xAA;
return !((x & odd) ^ odd);
}
通过python探索,yub认为可以先构造位掩码再利用^关系解决问题(使用移位运算符构造出奇数位全 1 的数 mask
,然后获取输入 x
值的奇数位,其他位清零(mask&x
),然后与 mask
进行异或操作,若相同则最终结果为 0,然后返回其值的逻辑非).
negate(x)
不使用
-
操作符,求-x
值.
yub认为此题非常基础.取反得补码+1即可.
/*
* negate - return -x
* Example: negate(1) = -1.
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 5
* Rating: 2
*/
int negate(int x) {
return ~x+1;
}
isAsciiDigit(x)
计算输入值是否是数字 0-9 的
ASCII
值.yub有惯性思维,(x-0x30>=0)&&(x-0x39<=0)
yub想到说用位操作,但是运用的时候还是很懵逼…
/*
* 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) {
int sign = 0x1<<31;
int upperBound = ~(sign|0x39);
int lowerBound = ~0x30;
upperBound = sign&(upperBound+x)>>31;
lowerBound = sign&(lowerBound+1+x)>>31;
return !(upperBound|lowerBound);
}
conditional(x, y, z)
使用位级运算实现 C 语言中的
x?y:z
三目运算符。又是位级运算的一个使用技巧。
yub今天无意间看到boolean觉得好像有点东西.
/*
* conditional - same as x ? y : z
* Example: conditional(2,4,5) = 4
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 16
* Rating: 3
*/
//如果!x=0,mask=000000000,y&~mask==y,z&mask==0
//如果x==0,mask=0xffffffff,y&~mask=y&0=0,z&mask=z
int conditional(int x, int y, int z) {
int mask = ~!x;
return (y & ~mask) | (z & mask);
}