csapp 02homework

2.60

unsigned replace_byte(unsigned x, int i, unsigned char b);

思路1,将 x 那个字节找到,然后移位到最后,更改为b,再移位回去。但是要加上 x 之前的后面字节,后面字节加上去这是个难点;

思路2,将 b 左移到与 x 中的字节 i 对应的位置,然后替换掉。

想了有半天时间了= =。

看了答案的解法,是将 b 左移到对应位置。然后将原来的 x 去掉对应 i 位置的字节,然后再加上这个 b 即可。b左移这个简单,就是 b << ( (sizeof(int)-i)>>3)。
关键是 x 如何去掉对应字节的值。设置掩码 然后用 x & mask,例如 x=0x12 34 56 78,则 x & mask = 0x12 00 56 78,那么这个掩码就应该是 ff 00 ff ff,如何得到这样的掩码。它的反 是 0x 00 ff 00 00 ,只需要将 0xff 左移这么多字节即可。

步骤:

①设置掩码 mask = 0xff

②掩码左移到对应字节位置 mask << ( (sizeof(int)-i) << 3),结果为 0xff 00 00

③掩码取反 ~mask,结果为 0xff 00 ff ff

④去掉x对应位置字节 x & ~mask,结果为 0x12 00 56 78

⑤b左移到对应字节为止 b << ( (sizeof(int)-i) << 3),结果为 0xAB 00 00

⑥将④和⑤步骤加和,④ | ⑤ = (x & ~mask) | (b...)

代码

#include 
#include 

unsigned replace_byte(unsigned x, int i, unsigned char b){
	if(i < 0){
		printf("error");
		return x;
	}
	if(i > sizeof(unsigned)-1){
		printf("error");
		return x;
	}
	unsigned mask = ((unsigned)0xFF) << (i << 3);
	unsigned pos_byte = ((unsigned)b) << (i << 3);
	return (x & ~mask) | pos_byte;
}

int main(){
	unsigned rep_0 = replace_byte(0x12345678, 2, ,0xAB);

	return 0;
}

2.61

写一个C表达式,在下列描述的条件下产生 1,而在其他情况下得到 0.假设 x 是int 类型。

A. x 的任何位 都等于 1.

x & 0xffffffff 

! ~x

 解释:如果x都为1,假设 1111 1111 那么 ~x 就是 0000 0000,然后 ! 是逻辑运算符,输出结果为 true(1)。

B. x 的任何位 都等于 0.

x & 0x00000000

!x

解释:若 x 全为0,如 0000 0000 那么 ! 00000000 输出 1. 

C. x 的最低有效字节中的位都等于 1

(x & 0xff) && 0xff 

!~(x | ~0xff)

0xff = 0x0000 00FF ,~0xFF就是 0xFFFF FF00, 如 x=0x0000 00ff,则 x | ~0xFF 就是 0xffff ffff 为全 1,之后操作跟如上道理一样。

D. x 的最高有效字节中的位 都等于 0

(x >> 3 & 0xff) && 0x00

如何取最高字节?x >> 24, 24怎么得来的。sizeof(int)-1 << 3 = 3 << 3 = 3 * 8 = 24 

!(x >> (sizeof(int)-1) << 3) & 0xff)

如 x = 0x0012 3456,则 x >> 24 为 0x00, 0x00 & 0xff = 0x00, 之后 ! 0x00,就是1啦。


2.62

编写一个函数 int_shifts_are_arithmetic(),在对 int 类型的数使用 算数右移 的机器上运行时这个函数 生成 1,而其他情况生成 0.
你的代码应该可以运行在任何字长的机器上。在几种机器上运行你的代码。

思路:

算数右移,正数无法判断。只能是负数,当执行算数右移的时候,高位补出来的数字都是 1,则说明该移位是 算术右移。

发现,直接判断最高位有效字节是否会变大,就可以判断是算数移位还是逻辑移位。变小肯定是逻辑移位。

分别取 移位前 移位后 的最高有效字节。

你可能感兴趣的:(CSAPP,笔记)