深入理解计算机系统(第二版) 家庭作业 第二章

本文详细介绍了《深入理解计算机系统》第二章的家庭作业,涵盖了位操作、移位、溢出检测、浮点数表示等多个主题。涉及到的题目包括整数位移、字节提取、整数溢出判断、位级编码规则、浮点数的比较和转换等,通过这些练习深入理解计算机底层运作原理。
摘要由CSDN通过智能技术生成

2.55-2.57 

2.58
int is_little_endian(){
    int a = 1;
    return *((char*)&a);
}

2.59
(x&0xFF) | (y&~0xFF)

2.60
unsigned replace_byte(unsigned x, unsigned char b, int i)
{
    return (x & ~(0xFF<<(i<<3))) | (b << (i<<3));
}

2.61
A. !~x
B. !x
C. !~(x>>((sizeof(int)-1)<<3))
D. !(x&0xFF)
注意,英文版中C是最低字节,D是最高字节。中文版恰好反过来了。这里是按中文版来做的。

2.62
这里我感觉应该是英文版对的,int_shifts_are_arithmetic()
int int_shifts_are_arithmetic(){
    int x = -1;
    return (x>>1) == -1;
}

2.63
对于sra,主要的工作是将xrsl的第w-k-1位扩展到前面的高位。
这个可以利用取反加1来实现,不过这里的加1是加1<<(w-k-1)。
如果x的第w-k-1位为0,取反加1后,前面位全为0,如果为1,取反加1后就全是1。
最后再使用相应的掩码得到结果。
对于srl,注意工作就是将前面的高位清0,即xsra & (1<<(w-k) - 1)。额外注意k==0时,不能使用1<<(w-k),于是改用2<<(w-k-1)。
 
int sra(int x, int k){
    int xsrl = (unsigned) x >> k;
    int w = sizeof(int) << 3;
    unsigned z = 1 << (w-k-1);
    unsigned mask = z - 1;
    unsigned right = mask & xsrl;
    unsigned left = ~mask & (~(z&xsrl) + z);
    return left | right;
}

int srl(unsigned x, int k){
    int xsra = (int) x >> k;
    int w = sizeof(int)*8;
    unsigned z = 2 << (w-k-1);
    return (z - 1) & xsra;
}

2.64
int any_even_one(unsigned x){
    return !!(x & (0x55555555));
}

2.65
int even_ones(unsigned x){
    x ^= (x >> 16);
    x ^= (x >> 8);
    x ^= (x >> 4);
    x ^= (x >> 2);
    x ^= (x >> 1);
    return !(x&1);
x的每个位进行异或,如果为0就说明是偶数个1,如果为1就是奇数个1。
那么可以想到折半缩小规模。最后一句也可以是 return (x^1)&1

2.66
根据提示想到利用或运算,将最高位的1或到比它低的每一位上,忽然想如果x就是10000000..该如何让每一位都为1。于是便想到了二进扩展。先是x右移1位再和原x进行或,变成1100000...,再让结果右移2位和原结果或,变成11110000...,最后到16位,变成11111111...。
int leftmost_one(unsigned x){
    x |= (x >> 1);
    x |= (x >> 2);
    x |= (x >> 4);
    x |= (x >> 8);
    x |= (x >> 16);
    return x^(x>>1);
}

2.67
A.32位机器上没有定义移位32次。
B.beyond_msb变为 2<<31。
C.定义 a = 1<<15; a<<=15; set_msb = a<<1; beyond_msb = a<<2;

2.68
感觉中文版有点问题,注释和函数有点对应不上,于是用英文版的了。
个人猜想应该是让x的最低n位变1。
int lower_one_mask(int n){
    return (2<<(n-1)) - 1;
}

2.69
unsigned rotate_right(unsigned x, int n){
    int w = sizeof(unsigned)*8;
    return (x>>n) | (x<<(w-n-1)<<1);
}

2.70
这一题是看x的值是否在 - 2^(n-1) 到 2^(n-1) - 1之间。
如果x满足这个条件,则其第n-1位就是符号位。如果该位0,则前面的w-n位均为0,如果该位为1,则前面的w-n位均为1。所以本质是判断,x的高w-n+1位是否为0或者为-1。
int fits_bits(int x, int n){
    x >>= (n-1);
    return !x || !(~x);
}

2.71
A.得到的结果是unsigned,而并非扩展为signed的结果。
B.使用int,将待抽取字节左移到最高字节,再右移到最低字节即可。
int xbyte(unsigned word, int bytenum){
    int ret = word << ((3 - bytenum)<<3);
    return ret >> 24;
}

2.72
A.size_t是无符号整数,因此左边都会先转换为无符号整数,它肯定是大于等于0的。
B.判断条件改为if(maxbytes > 0 && maxbytes >= sizeof(val))


2.73
请先参考2.74题。
可知:t = a + b时,如果a,b异号(或者存在0),则肯定不会溢出。
如果a,b均大于等于0,则t<0就是正溢出,如果a,b均小于0,则t>=0就是负溢出。
于是,可以利用三个变量来表示是正溢出,负溢出还是无溢出。
int saturating_add(int x, int y){
    int w = sizeof(int)<<3;
    int t = x + y;
    int ans = x + y;
    x>>=(w-1);
  • 23
    点赞
  • 148
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值