csapp第2章家庭作业(完善中)

chap2 homework

2.55 使用show_bytes程序,确定机器使用的字节-顺序

  • 重点语句

    typedef unsigned char *byte_pointer; //一定要用unsigned char *的指针
    printf ("%.2x", (unsigned char ) start[i]);  //没有unsigned char,printf会认为是有符号数int显示。原书提供存在这样的问题。
    
    typedef unsigned char *byte_pointer;
    static void show_bytes(const byte_pointer start, int len){
           int i;
           for (i =0 ; i<len; i++)
               printf("%.2x ",(unsigned char) start[i]);
           printf("\n");
     }
    

知识点:
1、show_bytes(byte_pointer start, int len)中形参是字符类型1个字节长的无符号类型指针,其+1的移动是对内存的物理位置的移动,可以真实显示内存的情况。
2、printf("%,2x",(unsigned char)start[i]);该语句的unsigned char强制转换,是必须的。因printf("%.2x")中会隐式转成int类型。显示高位时会按4字节长度显示。

2.56

试用不同的示例值运行show_bytes. 同2.55

2.57

试写show_short , show_long , show_double程序函数
​ 程序在chap2.c中。

2.58

编写一个is_little_endian函数,当在小端法机器上编译和f行时返回1,在大端法机器上编译运行时返回0.这个程序可运行在任何机器上,无论机器的字长是多少.

知识点:设定一个unsigned char * , 比较首字节是否与测试值0x12345中的低位值作比较。
程序在 chap2.58.c

typedef unsigned char *byte_pointer;
int is_little_endian(void)
{
	int test = 0x12345;
    show_bits((char *)&test, sizeof(int));
    byte_pointer id =(byte_pointer) &test;
	return id[0]==0x45;
}

2.59

编写一个C表达式,使它生成一个字,由x的最低有较字节和y中剩下的字节组成。例:x=0x89ABCDEF, y=0x76543210, 得到0x765432EF。

int splicingByte(int x, int y)
{
	return (x&0xff) | (y&~0xff);
} 

2.60

/*int replace_bytes(unsigned x, int i, char b)
Function: 用b替换x的i位置的1个字节
*/
unsigned replace_bytes(unsigned x , int i , unsigned char b){
	int mask = 0xff<<(i<<3);
	return (x&~mask) | (b<<(i<<3));
}

知识点:以上两题选定一个掩码,使用位的与、或运算达到对位的操作。

2.61

写一个表达式,在下列描述的条件一产生1,而在其他情况下得到0.Assume: x is int. 4个字节长度。
A. x的任何位都是1 . return !~x;
B. x的任何位都是0 . return !x ;
C. x的最低在效字节中的位都等于1. return !~((x &0xff)|0xffffff00)
D. x的最高有效字节中的位都等于0. return !((x >>((sizeof(int)-1)<<3) & 0xff));

知识点:C语言的 !逻辑非操作符,非运算表达式返回的结果是布尔值,TRUE返回1,FALSE返回0。(非零为TRUE,零为FALSE)

2.62

编写一个函数,在对int类型的数使用算术右移的机器上运行时,
这个函数生成1,而其他情况下生成0.代码应该可以运行在任何字长的机器上。
原理:算术右移补充符号位,而逻辑右移不会,因此用-1进行测试(或用~0).

int is_shifts_are_arithmetic(void){
	int x = -1;
	return x== x>>1;
}

2.63

写两个函数:srl--用算术右移来完成逻辑右移;sra用逻辑右移完成算术右移;

知识点:使用算术右移实现逻辑右移,关键在于消除算数右移带来的高位比特会填允为符号位,采用掩码运算消除这一影响即可。注意移位数k =0的情况。



2.83

一些数字的二进制表示是由形如0,yyyy...的无究串组成的,其中y是一个k位的序列。如 : \(\frac{1}{3}\) 的二进制表示是:0.01010101...(y=01,k=2)。

  1. 设由Y= \(B2U_k (y)\),这个数具在二进制表示y。给出一个由y和k组成的公式表示这个无穷串的值。提示:请考虑将十进制小数点右移k位的结果。

推导:

n = 0.yyyyy...
n<<k ==y.yyyyy... == y+n
(n <<k) - n = y
\((n* 2^k)\) - n =y 左移k相当乘以\(2^k\) ,提取n.
\(n*(2^k-1)\) =y
n= \(\frac{y}{2^k-1}\)

  1. 对于下列的y值,串的数值是多少?
    (a). 101 y=5,k=3, n= \(\frac{5}{2^3-1} = \frac{5}{7}\)
    (b). 0110 y=6,k=4, n=\(\frac{6}{2^4-1} = \frac{6}{15} = \frac{2}{5}\)
    (c). 010011 y=19,k=6 n=\(\frac{19}{2^6-1} = \frac{19}{63}\)

2.84

填写下列程序的返回值,这个程序测试它的第一个参数是否小于或者等于第二个参数。假定函数f2u返回一个无符号32位数字,其位表示与它的浮点参数桢。假设两个参数都不是NaN。两种0(+0、—0)被认为是相等的。

unsigned f2u(float x)
{
   return *(unsigned *)&x;
}
int float_le(float x, float y)
{
    unsigned ux = f2u(x);
    unsigned uy = f2u(y);
/*Get the sign bits*/
    unsigned sx = ux >>31;
    unsigned sy = uy >>31;
/*Give an expression using onle ux,uy, sx,and sy*/
    return  !(ux<<1 || uy<<1) ||  /*both zero*/
            (sx > sy) ||         /*x<0 and y>=0*/
            (!sx && !sy && ux <=uy) ||    /*x>=0 and y>=0*/
            (sx && sx && ux >= uy);       /*x <0 and y <0*/ 
}

2.85

2.85~2.88都是IEEE浮点格式。

A.数7.0.知识点: 从数据推位表达的逆算法:
1.将十进制数按\(v=(-1)^s *M*2^E\)形式表达。
2.以13.0为例,规格化数,s=0(正数),M=(1+f),E=3,\(V=(1+f)*2^3=2^3+2^3*f=13.0\)\(f=\frac{5}{8}=0.625。小数部分转二进制表示:\){0.625}_{10} ={0.101}_2$
3.综上,E=3=e-bias=e-127,\(e=130_{10}=10000010_{2},M=1+f=1.101_{2}\).

S E M
0 1000 0010 101 0000 0000 0000 0000 0000

B.知识点:
IEEE能够准确表描述的最大奇数E=23(小数部分位数n),f=1.1...111,其值为:\(2^{24}-1\) = 16777215.(e=150,E=e-bias=23).

C.知识点:
IEEE最小规格化数exp=0...1=e=1,M=1+f=1.00..0,其\(E=e-(2^{k-1}-1)=2-2^{k-1},V=1*2^{2-2^{k-1}}\),其倒数为\(2^{2^{k-1}-2}\),所以其E=\(2^{k-1}-2=126(k=8)\)

题目 E M f V bits
A 3 1.11 0.11 7.0 0 1000 0001 1100 00...0
B n=23 1.1...1 0.11...1 \(2^{n+1}-1\) 0 1001 0110 1111 11...1
C \(2^{k-1}-2\) 1 0.00...0 \(2^{2^{k-1}-2}\) 0 1111 1101 00...0

2.86

与Intel兼容的处理器也支持“扩展精度”浮点形式,这种格式具有80位字长,被分成1个符号位,k=15个阶码位,1个单独的整数位和n=63个小数位。整数位是IEEE浮点表示中隐含位的显示副本,也就是说对于规格化的值其为1,对于非规格化的值其为0.

  • 偏置量\(bias=2^{15-1}-1=2^{14}-1\)
  • \(非规格数E=1-bias=1-2^{14}+1=2-2^{14}\)
  • \(规格数E=e-bias=e-2^{14}+1\)
  • \(最小的正规格化数的e=1,E=e-2^{14}+1=2-2^{14}\)
  • 最大的规格化数e=\(2^{15}-2,E=e-bias=2^{15}-2^{14}-1\)
描述 十进制 备注
最小的正非规格化数 \(V=M*2^E=2^{-63}*2^{2-2^{14}}\) 3.6452e-4951 \(M=f=2^{-63}\)
最小的正规格化数 \(V=M*2^E=2^{2-2^{14}}\) 3.3621e-4932 \(M=1+f,f=0/2^{-63},M=1\)
最大的规格化数 \(V=M*2^E=2^{2^{15}-2^{14}-1}*(2-2^{-63})\) 1.189e+4932 \(M=1+f,f=(2^{63}-1)*2^{-63}=1-2^{-63},M=2-2^{-63}\)
posted on 2022-12-17 17:00  白菜根  阅读(306)  评论(0)    收藏  举报