【CS:APP】第二章 家庭作业

2017-06-14  本文已影响0人  gfson

版权声明:本文为 gfson 原创文章,转载请注明出处。
注:作者水平有限,文中如有不恰当之处,请予以指正,万分感谢。

2.55 - 2.57

2.55 - 2.57.png
#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_short(short x){
    show_bytes((byte_pointer) &x, sizeof(short));
}

void show_int(int x){
    show_bytes((byte_pointer) &x, sizeof(int));
}

void show_long(long x){
    show_bytes((byte_pointer) &x, sizeof(long));
}

void show_float(float x){
    show_bytes((byte_pointer) &x, sizeof(float));
}

void show_double(double x){
    show_bytes((byte_pointer) &x, sizeof(double));
}

int main(void){
    
    short s = 34;
    int i = 34;
    long l = 34L;
    float f = 34.0f;
    double d = 34.0;
    
    show_short(s);
    show_int(i);
    show_long(l);
    show_float(f);
    show_double(d);
    
    return 1;
}


上述代码运行后,结果如下:

result.png

对运行结果进行分析:

  1. 可以直观的看到当前计算机上各个类型所占的字节。其中,short 占 2 个字节, int、long、float 占 4 个字节,double 占 8 个字节。
  2. 可以看出当前机器字节顺序使用的是小端法。
  3. short、int、long 计算:2 * 16 + 2 = 34。
  4. float 计算:
  1. double 计算:

2.58

2.58.png
int is_little_endian(){
    int a = 1;
    return *((char*)&a);
}

int main(void){ 
    int result = is_little_endian();
    printf("result is: %d \n",result);
    return 1;
}

2.59

2.59.png
int mix(int x, int y){
    return (x & 0xFF) | (y & (~0xFF));
}

int main(void){ 
    int result = mix(0x89AECDEA,0x76743210);
    printf("result is: %x \n",result);
    return 1;
}

2.60

2.60.png
unsigned replace_byte_1(unsigned x, int i, unsigned char y){
    char* start = (char*)&x;
    start[i] = y;
    return x;
}

unsigned replace_byte_2(unsigned x, int i, unsigned char y){
    return (x & ~(0xFF<<(i<<3)) | (y << (i<<3)));
}

int main(void){ 
    unsigned result_1 = replace_byte_1(0x12345678, 2, 0xAB);
    printf("result_1 is: %x \n",result_1);
    unsigned result_2 = replace_byte_2(0x12345678, 3, 0xAB);
    printf("result_2 is: %x \n",result_2);
    return 1;
}

replace_byte_2 的解释:


位级整数编码规则

位级整数编码规则-1.png 位级整数编码规则-2.png

接下来的作业需要遵循位级整数编码规则

2.61

2.61.png

经验

  1. 核心判断是零与非零,目的是需要达到在一种情况下结果所有位为 0,其他情况下有些位不为 0。
  2. 在 D 中,可以通过 x & (~0xFF) 的方法使得除最高位字节以外的字节都为 0,也可以通过 (x>>((sizeof(int)-1)<<3)) 的方法将最高位右移至最低位,来判断结果所有位是否为 0。

2.62

2.62.png
int int_shifts_are_arithmetic_1(){
    return !(((0xFF<<((sizeof(int)-1)<<3))>>((sizeof(int)-1)<<3)) + 0x01 );
}

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

int main(void){ 
    int result_1 = int_shifts_are_arithmetic_1();
    printf("result_1 is: %d \n",result_1);
    int result_2 = int_shifts_are_arithmetic_2();
    printf("result_2 is: %d \n",result_2);
    return 1;
}

经验

  1. 第一种方法,0xFF 先左移到最高字节,然后右移到最低字节,判断其所有位是否为 1。
  2. 第二种方法,非常巧妙,通过 -1 既 0xFFFFFFFF 右移一位判断其值是否改变。

2.63

2.63.png
unsigned srl(unsigned x, int k){
    unsigned xsra = (int) x >> k;
    int w = sizeof(int)*8;
    unsigned z = 2 << (w-k-1);
    return (z - 1) & xsra;
}

int sra(int x, int k){
    int xsrl = (unsigned) x >> k;
    int w = sizeof(int) << 3;
    unsigned z = 1 << (w-k-1);
    unsigned mask = z - 1;
    unsigned right = mask & xsrl;
    unsigned left = ~mask & (~(z&xsrl) + z);
    return left | right;
}

int main(void){ 
    unsigned result_srl = srl(-1,1);
    printf("result_srl is: %x \n",result_srl);
    int result_sra = sra(-1,1);
    printf("result_sra is: %x \n",result_sra);
    return 1;
}

运行结果如下:

Result.png

解析

  1. 对于 srl,目的就是将前面的高位清 0,即 xsra & (1<<(w-k) - 1)。额外注意 k==0 时,不能使用 1<<(w-k),于是改用 2<<(w-k-1)。
  1. 对于 sra,目的是将 xrsl 的第 w-k-1 位扩展到前面的高位。这个可以利用取反加 1 来实现,不过这里的加 1
    是加 1<<(w-k-1)。如果 x 的第 w-k-1 位为 0,取反加 1 后,前面位全为 0,如果为 1,取反加 1 后就全是 1。最后再使用相应的掩码得到结果。

2.64

2.64.png
int any_odd_one(unsigned x){
    return !!(x & 0x55555555);
}

int main(void){ 
    int result = any_odd_one(0xaaaaaaaa);
    printf("result is: %d \n", result);
    return 1;
}

解析

2.65

2.65.png
int odd_ones(unsigned x){
    x = x ^ (x >> 1);  
    x = x ^ (x >> 2);  
    x = x ^ (x >> 4);  
    x = x ^ (x >> 8);  
    x = x ^ (x >> 16);  
    return x & 1;  
} 

int main(void){ 
    int result = odd_ones(9);
    printf("result is: %d \n", result);
    return 1;
}

解析

2.66

2.66.png
int leftmost_one(unsigned x){
    x |= (x >> 1);
    x |= (x >> 2);
    x |= (x >> 4);
    x |= (x >> 8);
    x |= (x >> 16);
    return x^(x>>1);
}

int main(void){ 
    int result = leftmost_one(0x9f);
    printf("result is: %x \n", result);
    return 1;
}

解析

2.67

2.67.png
int bad_int_size_is_32(){
    int a = 1<<15; 
    a<<=15; 
    int set_msb = a<<1; 
    int beyond_msb = a<<2;
    return set_msb && !beyond_msb;
}
int main(void){ 
    int result = bad_int_size_is_32();
    printf("result is: %d \n", result);
    return 1;
}

解析

2.68

2.68.png
int lower_one_mask(int n){
    return (2 << (n-1)) - 1;
}

int main(void){ 
    int result = lower_one_mask(32);
    printf("result is: %x \n", result);
    return 1;
}

2.69

2.69.png
unsigned rotate_left(unsigned x, int n){
    return (x << n)|(x >> 1 >> ((sizeof(int)*8)- n -1));
}

int main(void){ 
    unsigned result = rotate_left(0x12345678, 32);
    printf("result is: %x \n", result);
    return 1;
}

2.70

2.70.png
int fits_bits(int x, int n){
    x >>= (n-1);
    return !x || !(~x);
}

int main(void){ 
    int result = fits_bits(8, 4);
    printf("result is: %d \n", result);
    return 1;
}

解析

2.71

2.71.png
int xbyte(packed_t word, int bytenum){
    int ret = word << ((3 - bytenum)<<3);
    return ret >> 24;
}

解析

2.72

2.72.png

解析

2.73

2.73.png
#include <limits.h>

int saturating_add(int x, int y){
    int w = sizeof(int)<<3;
    int t = x + y;
    int ans = x + y;
    x>>=(w-1);
    y>>=(w-1);
    t>>=(w-1);
    int pos_ovf = ~x&~y&t;
    int neg_ovf = x&y&~t;
    int novf = ~(pos_ovf|neg_ovf);
    return (pos_ovf & INT_MAX) | (novf & ans) | (neg_ovf & INT_MIN);
} 

int main(void){ 
    int result = saturating_add(INT_MIN, -1);
    printf("result is: %x \n", result);
    return 1;
}

解析

思路

2.74

2.74.png
#include <stdint.h>

int tsub_ok(int x, int y){
    int w = sizeof(int)<<3;
    int t = x - y;
    x>>=(w-1);
    y>>=(w-1);
    t>>=(w-1);
    return !((x != y) && (y == t));
}

int main(void){ 
    int result = tsub_ok(INT32_MIN, 1);
    printf("result is: %d \n", result);
    return 1;
}

解析

2.75

2.75.png
unsigned unsigned_high_prod(unsigned x, unsigned y){
    int w = sizeof(int)<<3;
    return signed_high_prod(x, y) + ((int)x>>(w-1)) & y + ((int)y>>(w-1)) & x;
}

解析

2.76

2.76.png

2.77

2.77.png

2.78

2.78.png
int divide_power2(int x, int k){
    int ans = x>>k;
    int w = sizeof(int)<<3;
    ans += (x>>(w-1)) && (x&((1<<k)-1));
    return ans;
} 

解析

2.79

2.79.png

// TODO

上一篇 下一篇

猜你喜欢

热点阅读