cs:app 第二章homework(已完结)

主要完成mod 4==0的题目,有错误望指正, 这是学校课程的作业,但是由于能力有限,题目有时也会参考其他的答案,

我觉得很好的一份答案:https://dreamanddead.gitbooks.io/csapp-3e-solutions/chapter2/2.68.html

写博客的目的是为了加深我自己的理解而已,而不是表明这些都是完完全全的我自己的开创性解答。

全篇可能使用到的函数(来自书中给出的)

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("
");
}
void show_int(int x)
{
    show_bytes((byte_pointer)&x,sizeof(int));
}

2.55

这里show_bytes.c文件可以在官网csapp.cs.cmu.edu/3e/code.html下载。

这里需要学习的是Linux环境下c程序的编写:写好xxx.c文件,然后运行gcc xxx.c,最后会发现多出一个a.out文件,然后在命令行输入./a.out即可看到编译运行的结果了。

2.58

 int is_little_endian(byte_pointer start)
{
    if(start[0]==0xff) return 1;
    else return 0;
}
int main()
{
    size_t m =0xff;
    //byte_pointer start = (byte_pointer &m);
    if(is_little_endian((byte_pointer)&m)==1) printf("应是小端机");
    else printf("我猜是大端机");
    return 0;
}

为什么我觉得小端机这么好听呢?

不觉让人想到宋词《九张机》:

   一张机,采桑陌上试春衣。风晴日暖慵无力, 桃花枝上,啼莺言语,不肯放人归。
  两张机,行人立马意迟迟。深心未忍轻分付, 回头一笑,花间归去,只恐被花知。
  三张机,吴蚕已老燕雏飞。东风宴罢长洲苑, 轻绡催趁,馆娃宫女,要换舞时衣。
  四张机,咿哑声里暗颦眉。回梭织朵垂莲子,盘花易绾,愁心难整,脉脉乱如丝。
  五张机,横纹织就沈郎诗。中心一句无人会, 不言愁恨,不言憔悴,只恁寄相思。
  六张机,行行都是耍花儿。花间更有双蝴蝶,停梭一晌,闲窗影里,独自看多时。
  七张机,鸳鸯织就又迟疑。只恐被人轻裁剪,分飞两处,一场离恨,何计再相随?
  八张机,回纹知是阿谁诗?织成一片凄凉意,行行读遍,恹恹无语,不忍更寻思。
  九张机,双花双叶又双枝。薄情自古多离别,从头到尾,将心萦系,穿过一条丝。

 2.59

这里主要用到的是 一个并和或的运用 m = ((x&sign)|(y&~sign))

int main()
{
    size_t sign = 0xff; //size_t == unsigned int
    size_t x = 0x89ABCDEF;
    size_t y = 0x76543210;
    size_t m = ((x&sign)|(y&~sign));
    show_int(m);

    return 0;
}

2.60

unsigned replace_byte (size_t x ,int i,unsigned char b)
{
    size_t k =x;
    size_t n =(unsigned)i<<3;
    size_t sign = 0xff<<n;
    size_t sb = (unsigned)b<<n;
    return (k & ~sign) | sb;

}
int main()
{
    size_t x;
    size_t y;
    x = replace_byte(0x12345678,2,0xAB);
    y = replace_byte(0x12345678,0,0xAB);
    show_int(x);
    show_int(y);

}

 2.64

C语言中!!操作表示:把这个数非零转化为1,0还是零。因为这里是逻辑判断功能,非零即为真,只有零才是假。

题目是return 1 when any odd bit of x equals 1;0 otherwise只有我一个人疑惑奇数bit是那些偶数bit是那些吗?

百度之后  :  0101110  那么奇数位就是 0 0 1 0 果然我想太多

int any_odd_one(unsigned x)
{
    return !!(x & 0xAAAAAAAA);
}
int main()
{
   printf("%d",any_odd_one(0x5));
   return 0;
}

(any 是任何一个就行,不是every。。。。。我的英文。。。要哭了。。。。)

2.68

参考思路为:https://dreamanddead.gitbooks.io/csapp-3e-solutions/chapter2/2.68.html

我开始没有理解题目的意思:

mask with least signficant n bits set to 1,现在理解,可能是把除最高位以外的其他位的权值都设为1吧,(或者 是理解为让n这个数的最低n位都变为1,就是有n个1的数那么我看到别人的思路blog.csdn.net/zhanyu1990/article/details/24936663用2<<(n-1)) - 1也很巧妙)

int lower_one_mask(int n)
{
    int w = sizeof(int)<<8;
    return (unsigned)-1>>(w-n); //注意这里的-1一定要是强制转为无符号 
}
int main()
{
    show_int(lower_one_mask(6));
show_int(lower_one_mask(17)); }

2.72

其实我不是很懂怎么通过main 函数使用这个函数,所以参考了:https://dreamanddead.gitbooks.io/csapp-3e-solutions/chapter2/2.72.html

void copy(int val,void *buf,int maxbytes)
{
    if(maxbytes-(int)sizeof(val)>=0)
    {
        memcpy(buf,(void *)&val,sizeof(val));
        printf("right
");
    }
    else printf("Errrrrr
");
}

int main()
{
   int maxbytes = sizeof(int) * 10;
  void* buf = malloc(maxbytes);
  int val;

  val = 0x12345678;
  copy(val, buf, maxbytes);
  val = 0xAABBCCDD;
  copy(val, buf, 0);
  free(buf);
  return 0;
}

这道题目题目中有提示:sizeof 运算返回的是无符号,所以判断大小的那一句由于是无符号的数,自然是全部>=0,改进的方法也很简单,强制类型转化,变为有符号数的操作即可。

2.76

1.void *malloc(size_t size);

作用:可以向系统申请分配指定size个字节的内存空间

2.void *memset(void *s,int c,size_t n)

作用:将已开辟内存空间 s 的首 n 个字节的值设为值 c

void *cccalloc(size_t nmemb,size_t size)
{
    if(nmemb==0||size==0) return NULL;
    size_t buf_size = nmemb * size;
    if (nmemb == buf_size / size) //判断是否溢出
    {
       void* ptr = malloc(buf_size);
       memset(ptr, 0, buf_size);
       return ptr;
     }
    return NULL;

}
int main()
{
  void* p;
  p = cccalloc(0x1234, 1);
  if(p!=NULL)
   printf("rigjt!
");
  free(p);

  p = cccalloc(SIZE_MAX, 2);//SIZE_MAX定义在头文件stdint.hif(p == NULL)
    printf("ERRRR
");
  free(p);
  return 0;
}

 2.84

unsigned f2u(float x)
{
    return  *(unsigned*)&x;//&x取x的地址,(unsigned*)&x是把x的地址强制类型转换为unsigned,*(unsigned*)&x取转换后的值
}
int float_le(float x,float y)
{

  unsigned ux = f2u(x);
  unsigned uy = f2u(y);

  unsigned sx = ux >> 31;
  unsigned sy = uy >> 31;
    //浮点数的一个特点就是,如果大于0,则可以按unsigned位表示的大小排序。
//如果小于0则相反。注意都为0的情况即可。
//所以条件是:
   return ((ux<<1)==0 && (uy<<1)==0) ||
    (!sx && sy) ||
    (!sx && !sy && ux <= uy) ||
    (sx && sy && ux >= uy);



}
int main()
{
  printf("%d",(float_le(+0, -0)));
  printf("%d",(float_le(2, 3)));
}

2.88

格式A 格式B
1 01110 001 -9/16 1 0110 0010 -9/16
0 10110 101 208 0 1110 1010 208
1 00111 110 -7/1024 1 0000 0111 -7/1024
0 00000 101 2^(-11)*5 0 0000 0001 2^(-10)
1 11011 000 -2^12 1 1110 1111 2^7*31/16
0 11000 100 2^4*3/2 0 1111 0000 +无穷

2.92

typedef unsigned float_bits;
float_bits float_negate(float_bits x)
{
    unsigned exp = (x>>23)&0xff;
    unsigned frac = x&0x7fffff;
    if((exp ==0xff)&&(frac!=0) ) return x;
    else return  x^0x80000000;
}

最高位取反即可

2.96

int float_f2i(float_bits x)
{
    unsigned sign =x>>31;
    unsigned exp = (x>>23)&0xff;
    unsigned frac = x&0x7fffff;
    unsigned bias = 0x7F;
    int int_x;
    unsigned E;
    unsigned M;
    if(exp>=0 &&(exp<bias))  int_x = 0; // x less than 1 ,than convert it to 0
    else if((exp-bias)>=31)  int_x = 0x80000000;
    else
    {
        E = exp - bias ;
        M = frac | 0x800000;
        if (E > 23) {
      int_x = M << (E - 23);
    } else {
      int_x= M >> (23 - E);
    }
    }
    return sign? -int_x:int_x;
}
原文地址:https://www.cnblogs.com/blairwaldorf/p/7604376.html