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)。
- 设由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}\)
- 对于下列的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}\) |