深入理解计算机系统:第一章的家庭作业
2017-08-29 15:49 ZengGW 阅读(1156) 评论(0) 编辑 收藏 举报2.42 编写一个c表达式,生成一个字,由x的最低有效字节和y中剩下的字节组成。对于对于运算数 x = 0x89ABCDEF 和 y = 0x76543210,生成的结果是0x765432EF
答:分析一下,
a>. 这道题目主要考的是咱们逻辑运算的使用,首先咱们来回顾一下都有哪些逻辑运算:
按位与(&):(双目运算)相同位均为1,结果为1,否则结果为0
按位或(|):(双目运算)相同位有一个是1的结果为1,否则结果为0
按位异或(^):(双目运算)相同位值相同的结果为0,否则为1
按位取反(~):这是单目运算,有效位值是1的,结果为0,值为0的结果为1
还有其他的几个运算:什么同一运算、位移运算(左移位运算<<;右移位运算>> 又分为正数和负数,正数跟左移位运算一样,负数就分为逻辑运算补0,算术运算补1的区别)
b>. 从结果来看0x765432EF的前三位是y的前三位0x76543200,最后一位是x的最后一位0x000000EF,能否通过逻辑运算来分别得到呢?
0x76543200:y1 = y & 0xffffff00 == 0x76543210 & 0xffffff00 = 0x76543200
0x000000EF:x1 = x & 0x000000ff == 0x89ABCDEF & 0x000000ff = 0x000000EF
最后两个结果(y1 + x1 或者使用按位或运算 x1 | y1两种方式都行)代码如下:
#include <stdio.h> int main(void) { int x, y; int x1, y1, r1; printf("Please is a x and y: "); scanf("%x %x", &x, &y); printf("x = %.8x and y = %.8x\n", x, y); x1 = x & 0x000000ff; y1 = y & 0xffffff00; //r1 = x1 + y1;//这种是相加的方法 r1 = x1 | y1;//这种还是使用了逻辑运算按位或运算,相同位值有1的结果为1,不然结果为0 printf("x1 = %.8x and y1 = %.8x and r1 = %.8x\n", x1, y1, r1); return 0; }
2.43 只用位级和逻辑运算,编写出c表达式,在下列描述情况下产生1,而其他情况下得到0,你的代码应该能在所以字长的机器上运行,加上x是正数:
A. X的任何位都等于1 B. x的任何位都等于0 C. x的最低有效字节中的位都等于1 D. X的最低有效位的字节都等于0
答:位级和逻辑运算在上一题中已经回顾,分析以下四种情况:
A. X的任何位都等于1:这个可以使用 按位或(|)运算来实现,比如x = 0x00000001 ===> x | 0xffffffff = 0xffffffff,或者使用取反再按位异或 ~x ^ x或者取反再按位或~x | x
B. X的任何位都等于0:使用按位异或,相同位0,反之为1,x ^ x
C. X的最低有效位字节位都为1:使用按位或运算或者算术右移运算
D. X的最低有效位字节位都为0:左移运算或者按位与运算
2.44 编写一个函数is_shifts_are_arithmetic(),使得这个函数在对整数使用算术右移的机器上运行时生成1,而其他情况下生成0,你的代码用该可以运行在任何字长的机器上。在几种机器上测试你的代码,编写并测试过程unsigned_shifts_are_arithmetic(),该过程确定对无符号整数使用的位移形式。
答:分析一下:这道题主要考咱们位移运算:左位移、右位移(正数与左位移一样,负数分为逻辑运算补0、算术运算补1)
第一种情况:算术右移的机器上边,通过算术右移得到结果1,设想一下算术右移,左边补齐有效位的是1,那么这时候该怎么办呢?1 = 0 + 1这个表达式熟悉吗?对,就是二进制补码,设想一下,神马情况下通过右移,能得到0呢?算术右移补的是1,那么假设咱们先右移sizeof(int)位,得到的结果必然是所有的有效位都为1,怎么转换成0呢????有人想到取反,那你最后怎么加上1呢??那就是给右移后的数添加负号,仔细想一下,当所有有效位都是1的时候,添加一下负号,那结果会是什么???咱们来计算一下它x的补码(补码 = ~x +1),那么结果就是我们想要的
第二种情况:逻辑右移的机器上边,通过逻辑右移得到结果0,设想一下,什么情况下右移的结果会是0,很明显是当你右移到所有有效位都是0的时候,结果就为0了
基于上边的分析,什么情况下右移到整数结果全部为0呢??只有当右移sizeof(int)位,才能得到全为0(右移,逻辑运算,左边补0,右移几位截取掉几位,直到所有有效位都为0为止),由于程序需要通用,所有得到所有有效位全为0的数x,添加负号变成-x,咱们来计算它的补码,-x = ~x + 1 = 0(比如是4位 -x = -0000 = 1111 + 1 = 10000,保留4位有效数字,最高位截取掉后,剩余有效位是0000)
2.45