CSAPP 练习2.60

发布于:2022-11-28 ⋅ 阅读:(403) ⋅ 点赞:(0)

题目:假设我们将一个w位的字中的字节从0(最低位)到w/8-1(最高位)编号。写出下面C函数的代码,它会返回一个无符号值,其中参数x的字节i被替换成字节b:

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

以下示例,说明了这个函数该如何工作:

replace_byte(0x12345678,2,0xAB)-->0x12AB5678

replace_byte(0x12345678,0,0xAB)-->0x123456AB

函数条件略.........

答题思路

按照示例中的数字规则,当i=2,b=0xAB时,要将0x12345678=>0x12AB5678,首先认为0x12AB5678由 0x12AB0000^0x5678而来,再0x12AB0000由0x1200^0xAB而来,0x1200由0x1234&(~0xFF)来,而0x1234与0x5678均可通过0x12345678根据i进行位移运算获得,根据此思路写下如下代码:

#include <stdio.h>
unsigned repace_byte(unsigned x,int i,unsigned char b){
	int vv=sizeof(int);
	printf("((vv-i)<<3) %d \n",((vv-i)<<3));
	unsigned d=x<<((vv-i)<<3);
	printf("d %.2x \n",d);
	 d=d>>((vv-i)<<3);  //获取i后字节;
		printf("d2 %.2x \n",d);
	unsigned c=x>>(i<<3); //获取i字节之前;
	printf("c %.2x \n",c);
	 c=c&(~0xFF);
	printf("c2 %.2x \n",c);
	 c=c^b;
		printf("c^b %.2x \n",c);
	c=c<<((i)<<3);
	printf("c3 %.2x \n",c);
	c=c^d;
	return c;
}
int main()
{
   /* 我的第一个 C 程序 */
   printf("Hello, World! %.2x \n",repace_byte(0x12345678,2,0xAB));

   return 0;
}

经过运行,当i=1、2、3时均可取得正确结果,但是i=0时结果并不正确。经过确认,unsigned的长度位32位,左移32位将获得它自身,与期望左移32位不相符.

。。。纠结了一晚怎么在i=0的时候将d变成0!

Later

        参考大佬的答案http://t.csdn.cn/cJqW4

大佬的思路与官方答案思路一样:是将b左移8*i位,如i=0,则不移动,则b移动后为0xAB,然后通过表达式x&(~(0xFF << i * 8))将x变成0x12345600,如果i=1,x=0x12340078,b=0xAB00。最后x|b可获得正确结果。

 反思:此题隐约意识到会使用到0xFF常量,事实上也用到了,但是对位移运算的掌握程度不牢固。


网站公告

今日签到

点亮在社区的每一天
去签到