(CSAPP第三版系列)导航篇传送门
2.56 用不同的示例值运行show_bytes的代码。
#include <stdio.h> typedef unsigned char *byte_pointer; void show_bytes(byte_pointer start, size_t len) { size_t i; for(i = 0;i < len;i++) printf("%.2x",start[i]); printf("\n"); } void show_int(int x) { show_bytes((byte_pointer)&x,sizeof(int)); } void show_float(float x) { show_bytes((byte_pointer)&x,sizeof(float)); } void show_pointer(void *x) { show_bytes((byte_pointer)&x,sizeof(void *)); } int main() { int x = 15213; float y = 152.13; void *z = (void *)&x; show_int(x); show_float(y); show_pointer(z); return 0; }
/*测试结果:
6d3b0000 //show_int(15213);
48211843 //show_float(152.13);
04ff6100 //show_pointer((void *)&x);
*/
2.60 写出该C函数代码unsignedreplace_byte(unsigned x,int I,unsigned char b)。
//由题意及x86-64为小端法机器编写程序 #include <stdio.h> typedef unsigned char *byte_pointer; unsigned replace_byte(unsigned x,int i,unsigned char b); int main() { for(int i = 0;i < sizeof(unsigned);i++) printf("%x\n",replace_byte(0x12345678,i,0xab)); return 0; } unsigned replace_byte(unsigned x,int i,unsigned char b) { byte_pointer pt = (byte_pointer)&x; //pt保存x地址 *(pt + i) = b; //x的i字节替换成字节b unsigned y = *((unsigned *)pt); //pt指向的unsigned数字 return y; }
/*测试结果:
123456ab //replace_byte(0x12345678,0,0xab);
1234ab78 //replace_byte(0x12345678,1,0xab);
12ab5678 //replace_byte(0x12345678,2,0xab);
ab345678 //replace_byte(0x12345678,3,0xab);
*/
2.64写出代码实现该函数 int any_odd_one(unsigned x)
#include <stdio.h> int any_odd_one(unsigned x) { return 0 != (x&0xaaaaaaaa); } int main() { printf("%d\n",any_odd_one(0x5)); //二进制表示 00000000 00000000 00000000 00000101 printf("%d\n",any_odd_one(0x25));//二进制表示 00000000 00000000 00000000 00100101 printf("%d\n",any_odd_one(0x7)); //二进制表示 00000000 00000000 00000000 00001101 return 0; }
/*测试结果
0
1
1
*/
2.68 写出具有如下原型的函数的代码:int lower_one_mask(intn);
#include <stdio.h> #include <limits.h> int lower_one_mask(int n) { unsigned x = ((INT_MAX)<<1) + 1u; //x位模式:1111111111111111... return (int)(x>>((sizeof(int)<<3)-n)); //对x移位实现函数的功能 } int main() { for(int i = 1;i <= sizeof(int)<<3;i++) printf("%x\n",lower_one_mask(i)); return 0; }
/*测试结果:
1 //lower_one_mask(1)
3 //lower_one_mask(2)
7 //lower_one_mask(3)
f //lower_one_mask(4)
1f //lower_one_mask(5)
3f //lower_one_mask(6)
7f //lower_one_mask(7)
ff //lower_one_mask(8)
…
3fffffff //lower_one((sizeof(int)<<3)-2);
7fffffff //lower_one((sizeof(int)<<3)-1);
ffffffff //lower_one(sizeof(int)<<3);
*/
2.72 voidcopy_int(int val,void *buf,int maxbytes);
A. 解释为什么代码中的条件测试总是成功。
sizeof(val)结果类型为size_t,在maxbytes-sizeof(val)时按无符号数进行运算,
则运算结果仍然为无符号数,所以if条件"maxbytes-sizeof(val)>=0"恒成立。
B. 如何重写这个条件测试,使之工作正确。
void copy_int(int val,void *buf,int maxbytes) { if(maxbytes >= (int)sizeof(val)) memcpy(buf,(void *)&val,sizeof(val)); }
2.76 编写calloc的实现,通过调用malloc执行分配,调用memset将内存设置为0。
#include <stdlib.h> #include <string.h> void *calloc(size_t nmemb,size_t size) { if(nmemb == 0 || size == 0) return NULL; else { /*使用cnt作为malloc(),memset()函数的参数,避免由算数溢出引起的漏洞。*/ size_t cnt = nmemb * size; pt = (void *)malloc(cnt); if(pt != NULL) memset(pt,0,cnt); return pt; } }
2.80 写出函数threefourths的代码。
#include <stdio.h> int threefourths(int x) { /*基本思路:3/4x=1/4x+1/2x。对于舍入误差来说,只与 符号位和最低两位有关。据此编写程序。*/ int a = x>>((sizeof(int)<<3)-1); int b = x & 1; int c = (x & 3 - b)>>1; int diff = b + c; int mis = !a && !(b==0&&c==0); return (x>>2)+(x>>1)+diff-mis; } int main() //测试程序 { printf("i threefourths(i) 3*4/i\n"); for(int i = -8;i <= 8;i++) printf("%2d %12d %12d\n",i,threefourths(i),3*i/4); return 0; }
/*测试结果:
i threefourths(i) 3*4/i
-8 -6 -6
-7 -5 -5
-6 -4 -4
-5 -3 -3
-4 -3 -3
-3 -2 -2
-2 -1 -1
-1 0 0
0 0 0
1 0 0
2 1 1
3 2 2
4 3 3
5 3 3
6 4 4
7 5 5
8 6 6
*/
2.84 填写程序的返回值。
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 only ux,uy,sx,and sy*/ return ((sx&&sy)&&(ux>=uy))||((!sx&&!sy)&&(ux<=uy))||(sx&&!sy); //三种可能情况 }
2.88
2.92 实现该函数 float_bits float_negate(float_bitsf);
typedef unsigned float_bits float_bits float_negate(float_bits f) { unsigned sign = f >> 31; unsigned exp = f >> 23 & 0xff; unsigned frac = f & 0x7fffff; if(exp == 0xff && frac) return f; else return (exp << 23)|frac; }
2.96 实现该函数 int float_f2i(float_bits f);
int float_f2i(float_bits f) { unsigned sign = f>>31; unsigned exp = (f>>23) & 0xFF; unsigned frac = f & 0x7FFFFF; if (exp > 158) //超出表示范围 return (int) 0x80000000u; if (exp <= 126) //非规格化数处理 return (int) 0; /*由IEEE 754编码规则,编写程序*/ unsigned val = (0x80000000u | (frac << 8))>>(158-exp); /*下面考虑是否超出表示范围*/ if (!sign) return val > 0x7FFFFFFF ? 0x80000000u : val; else return val > 0x80000000u ? 0x80000000u : -val; }