欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Chapter 2 Representing and Manipulating Information

程序员文章站 2022-07-04 19:33:07
...

2020-03-25在自己博客园搬运过来…

Homework Problems

2.57

void show_short(short x)
{
    show_bytes((byte_pointer) &x, sizeof(short));
}

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

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

2.58

int is_little_endian()
{
    int a = 1;
      /*
    &a: 取a的地址

    (char*)&a: 将a的地址所在的位置的值视为字符型指针的地址

    *(char*)&a: 取a所在地址的第0个字节的值作为一个char类型返回

      */
    return *(char*)&a;
}

2.59

result = (x & 0xFF) | (y & (~0xFF));

2.60

unsigned replace_byte(unsigned x, int i, unsigned char b)
{
    int j;
    unsigned char c;

    j = 8 * i;
    b = b << j;
    c = ~(0xFF << j);
    return ((x & c) | b);
}

2.61

//A
bool result = !(x + 1);

//B
bool result = !x;

//C
bool result = !(~(x | (~0xFF)));

//D
bool result = !(~(x >> ((sizeof(int) - 1) << 3)));

2.62

bool shifts_are_arithmetic()
{
    /*这里不能写x = 0xFFFFFFFF,因为int不一定是32位的*/
    int x = -1;
    return !(x ^ (x >> ((sizeof(int)));
}

2.63

unsigned srl(unsigned x, int k)
{
    /*Perform shift arithmetically*/
    unsigned xsra = (int)x >> k;
    int w = sizeof(int) << 3;
    unsigned y = 2 << (w - k - 1);
    return (y - 1) & xsra;
}

int sra(int x, int k)
{
    /*Perform shift logically*/
    int xsrl = (unsigned)x >> k;
    int w = sizeof(int) << 3;
    int y = -1 << (w - k - 1);
    int z = (~((xsrl & y) + y) & y) << 1;
    return xsrl | z;
}

2.64

int any_odd_one(unsigned x)
{
	return !(~(x | 0x55555555));
}

2.65

/*Return 1 when x contains an odd number of 1s; 0 otherwise. Assume w = 32*/
int odd_ones(unsigned x)
{
    x ^= x >> 1;
    x ^= x >> 2;
    x ^= x >> 4;
    x ^= x >> 8;
    x ^= x >> 16;
    return x & 1;
}

2.66

/*Generate mask indicating leftmost 1 in x. Assume w = 32
 *For example, 0xFF00->0x8000, and 0x6600->0x4000.
 *If x = 0, then return 0.
 */
int leftmost_one(unsigned x)
{
    x |= x << 1;
    x |= x << 2;
    x |= x << 4;
    x |= x << 8;
    x |= x << 16;
    return x ^ (x >> 1);
}

2.67

//A
Right shift, only with shift amounts between 0 and w - 1, and w is 32.

//B
int int_size_32()
{
    int set_msb = 1 << 31;
    int beyond_msb = 2 << 31;
    return set_msb && !beyond_msb;
}

//C
int int_size_16()
{
    int set_msb = 1 << 15;
    int beyond_msb = 2 << 15;
    return set_msb && !beyond_msb;
}

2.68

/*Mask with least significant n bits set to 1. Assume 1 <= n <= 32*/
int lower_one_mask(int n)
{
    unsigned x = 0xFFFFFFFF;
    return x >> (32 - n);
}

2.69

unsigned rotate_left(unsigned x, int n)
{
	return (x << n) | (x >> ((sizeof(int) << 3) - n));
}

2.70

/*Return 1 when x can be represented as an n_bit, 2's-complement number;
 *0 otherwise. Assume 1 <= n <= w*/
int fits_bits(int x, int n)
{
    return (x >> n == 0) || (~(x >> n) == 0);
}

2.71

//A
The type of return value of the function is unsigned int, but it needs signed int.

//B
int xbyte(packed_t word, int bytenum)
{
    return (int)((word << ((3 - bytenum) << 3)) >> 24);
}

2.72

A:
The type of the value of “maxbytes - sizeof(val)” is unsigned.
B:
if (maxbytes >= sizeof(val))

2.73

/*Addition that saturates to TMin or TMax*/
int saturating_add(int x, int y)
{
    int sum = x + y;
    int x_sign = x >> (w - 1);        //X的符号位
    int y_sign = y >> (w - 1);        //Y的符号位
    int sum_sign = sum >> (w - 1);    //Sum的符号位
    int pos_overflow = !x_sign && !y_sign && sum_sign;    //判断正溢出
    int neg_overflow = x_sign && y_sign && !sum_sign;    //判断负溢出
    int overflow = pos_overflow || neg_overflow;    //设置溢出位
    /*将溢出位设置扩展为位模式(全1或全0)*/
    overflow <<= (w - 1);
    overflow >>= (w - 1);
    /*根据是否溢出进行选择*/
    return (sum & ~overflow) + ((INT_MAX + !pos_overflow) & overflow);
}

2.74

/*Determine whether arguments can be subtracted without overflow*/
int tsub_ok(int x, int y)
{
    int sum = x - y;
    int x_sign = x >> (w - 1);        //X的符号位
    int y_sign = y >> (w - 1);        //Y的符号位
    int sum_sign = sum >> (w - 1);    //Sum的符号位
    int pos_overflow = !x_sign && y_sign && sum_sign;    //正溢出
    int neg_overflow = x_sign && !y_sign && !sum_sign;    //负溢出
    return !(pos_overflow || neg_overflow);
}

2.75

unsigned unsigned_high_prod(unsigned x, unsigned y)
{
    uint64_t msb_x = (uint64_t)x >> ((sizeof(x) << 3) - 1);
    uint64_t msb_y = (uint64_t)y >> ((sizeof(x) << 3) - 1);
    uint64_t goal = (int)x * (int)y + signed_high_prod(x, y) << (sizeof(int) << 3) + (x * msb_y + y + msb_x) << (sizeof(int) << 3) + (msb_x * msb_y) << (((sizeof(int) << 3) << 1) - 1) << 1;
    return goal >> (sizeof(int) << 3);
}

2.76

/*通过调用malloc执行分配,调用memset将内存设置为0*/
void *calloc(size_t nmemb, size_t size)
{
    if (nmemb == 0 || size == 0)
        return NULL;
    /*避免由算数溢出引起的程序漏洞*/
    size_t cnt = nmemb * size;
    p = (void *)malloc(cnt);
    if (p != NULL)
        memset(p, 0, cnt);
    return p;
}

2.77

//A
x = (x << 4) + x;

//B
x = x - (x << 3);

//C
x = (x << 6) - (x << 2);

//D
x = (x << 4) - (x << 7);

2.78

/*Divide by power of 2. Assume 0 <= k < w-1*/
int divide_power2(int x, int k)
{
    int w = sizeof(int) << 3;
    /*如果x < 0, k不变;如果x >= 0, 将k置为0*/
    int k = k & (x >> (w - 1));
    /*如果k不为0,进行偏置*/
    x += (1 << k) - 1;
    x >>= k;
    return x;
}

2.79

int mul3div4(int x)
{
    int k = 4;
    int y = (x << 2) - x;
    int w = sizeof(int) << 3;
    /*如果y < 0, k不变;如果y >= 0, 将k置为0*/
    k = k & (y >> (w - 1));
    /*如果k不为0,y加上偏置量; 反之,y不变*/
    y += (1 << k) - 1;
    y >>= k;
    return y;
}

2.80

/*no overflow means divide 4 first, then multiple 3*/
int threefourths(int x)
{
    int later = x & 0x3;
    int former = x & ~0x3;
    int w = sizeof(int) << 3;
    int bias = (x >> (w - 1)) & ((1 << 2) - 1);
    former >>= 2;
    former = (former << 1) + former;
    later = (later << 1) + later;
    later = (later + bias) >> 2;
    return later + former;
}

2.81

A:
x = (-1) << k;
B:
x = ((-1) << j) - ((-1) << (k + j));

2.82

/*这种题一般都是考虑0,INT_MIN, INT_MAX*/
//A 
(x < y) == (-x > -y)  false
if x = INT_MIN, y = 0;

//B
((x + y) << 4) + y - x == 17 * y + 15 * x  true

//C 
~x + ~y + 1 == ~(x + y)  true

//D
(ux - uy) == -(unsigned)(y - x)  true  

//E
((x >> 2) << 2) <= x   true

2.83

//A
set x equals the value of 0.yyyyy...
then x * (2 ^ k) = Y + x;
so x = Y / (2 ^ k - 1);

//B
(a)5/7
(b)6/15 = 2/5
(c)19/63

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 (ux << 1) == (uy << 1) ||        //+0与-0相等
           (!sx && sy) ||                    //x为负数,y为正数
           (sx && sy && (ux <= uy)) ||      //都为正数
           (!sx && !sy && (ux >= uy));      //都为负数
}

2.85

//A 
7.0 = V =  111.0(2进制)
s = 0; f = 0.11; M = 1 + f = 1.11; E = 2; e = E + bias = 2 + 2 ^ (k - 1) - 1 = 2 ^ (k - 1) + 1;
位表示(s~e~f) = 0~10...01~1100...000

//B
s = 0;
e_MAX = 11...1110 = 2 ^ k - 2; E_MAX = e_MAX - bias = 2 ^ k - 2 - (2 ^ (k - 1) - 1) = 2 ^ (k - 1) - 1;
一般来说, k < n; 所以当f = 0.111...; M = 1.111...(后面的1的个数为k位); V = 2 ^ (k + 1) - 1;
位表示(s~e~f) = 0~111...111~111...(k个1)00..00

//C
最小的正规格化数:
s = 0; e = 1; E = 2 - 2 ^ (k - 1); f = 0.000...; M = 1.000...; V = 2 ^ E;
它的倒数:
V1 = 2 ^ (-E); -E = 2 ^ (k - 1) - 2; e = 2 ^ k - 3; f = 0.000...;  M = 1.000...;
位表示(s~e~f) = 0~111...1101~000.000

2.86

Description Value Decimal
Smallest positive denormalized 0 000…(15)…(62)1 2^(1-Bias-63)
Smallest positive normalized 0 000(14)1 000…(63) 2^(1-Bias)
Largest normalized 0 111…(14)0 111…(63) 2^Bias * (2 - 2^(-63))

2.87

Description Hex M E V D
-0 8000 0 -14 -0 -0.0
Smallest value > 2 4001 1025/1024 1 1025/512 2.001953125
512 6000 1 9 512 512.0
Largest denormalized 03FF 1023/1024 -14 1023/(2^24) 1023/(2^24)
-∞ FC00 - - -∞ -∞
Number with hex representation 3BB0 3BB0 123/64 -1 123/128 0.9609375

2.88

Format A                                              Format B
---------------------------------------------------------------------------------                                 
Bits               Value                              Bits                 Value
01111 001        -9/8                               1 0111 0010          -9/8
10110 011        176.0                              0 1110 0110          176.0
00111 010        -5/1024                            1 0001 0011          -3/1024
00000 111        7/131072                           0 0000 0001          1/1024
11100 000        -8192.0                            1 1111 1111          -496.0
10111 100        384.0                              0 1111 1000          384.0

2.89

//A
(float) x == (float) dx   true

//B
dx - dy == (double) (x - y)   false
when y = INT_MIN

//C
(dx + dy) + dz == dx + (dy + dz)   true

//D
(dx * dy) * dz == dx * (dy * dz)  false
OVERFLOW!!!   when (dx * dy) overflows but (dy * dz) does not overflow.

//E    
dx / dx == dz / dz     false
when one of x and z is zero

2.90

float fpwr2(int x)
{
    /*Result exponent and fraction*/
    unsigned exp, frac;
    unsigned u;
    /*x is smallest positive denormalized number*/
    if (x < -149)
    {
        /*Too samll. Return 0.0*/
        exp = 0;
        frac = 0;
    }
    /*x is smallest positive normalized number*/
    else if (x < -126)
    {
        /*Denormalized result*/
        exp = 0;
        frac = (1 << (149 + x));
    }
    /*x is special value*/
    else if (x < 128)
    {
        /*Normalized result*/
        exp = x + 127;
        frac = 0;
    }
    else
    {
        /*Too big. Return +∞*/
        exp = 255;
        frac = 0;
    }

    /*Pack exp and frac into 32 bits*/
    u = exp << 23 | frac;
    /*Return as float*/
    return u2f(u);
}

2.91

//A
10000000 10010010000111111011011

//B
11.001001...001

//C
9th

2.92

/*Compute -f. If f is NaN, then return f.*/
float_bits float_negate(float_bits f)
{
    unsigned sign = f >> 31;
    unsigned exp = f >> 23 & 0xFF;
    unsigned frac = f & 0x7FFFFF;
    if ((exp == 0xFF && frac == 0) || (exp != 0xFF))
        sign = sign ^ 0x1;
    return (sign << 31) | (exp << 23) | frac;
}

2.93

/*Compute |f|. If f is NaN, then return f.*/
float_bits float_absval(float_bits f)
{
    unsigned exp = f >> 23 & 0xFF;
    unsigned frac = f & 0x7FFFFF;
    if (exp == 0xFF && frac != 0)
        return f;
    return (0 << 31) | (exp << 23) | frac;
}

2.94

/*Compute 2*f. If f is NaN, then return f.*/
float_bits float_twice(float_bits f)
{
    unsigned sign = f >> 31;
    unsigned exp = f >> 23 & 0xFF;
    unsigned frac = f & 0x7FFFFF;
    if (exp == 0xFF)
        return f;
    if (exp == 0)
        frac <<= 1;
    /*特殊值,此时乘以2要特别注意*/
    else if (exp == 0xFE)
    {
        exp = 0xFF;
        frac = 0;
    }
    else
        exp += 1;
    return (sign << 31) | (exp << 23) | frac;
}

2.95

/*Compute 0.5*f. If f is NaN, then return f.*/
float_bits float_half(float_bits f)
{
    unsigned sign = f >> 31;
    unsigned exp = f >> 23 & 0xFF;
    unsigned frac = f & 0x7FFFFF;
    if (exp == 0xFF)
        return f;
    /*round to even
--> 0 just >> 1
--> 0 (round to even) just >> 1
--> 1 just >> 1
--> 1 + 1(round to even) just >> 1 and plus 1*/
    unsigned flag = ((f & 0x3) == 0x3);
    if (exp == 0)
    {
        /*Denormalized*/
        frac = frac >> 1;
        frac += flag;
    }
    else if (exp == 1)
    {
        /*From normalized to denormalized*/
        exp = 0;
        frac = frac >> 1;
        frac += flag;
        frac |= 0x400000;
    }
    else
        /*normalized*/
        exp--;
    return (sign << 31) | (exp << 23) | frac;
}

2.96

/*Compute (int)f. If conversion overflow or f is NaN, return 0x80000000*/
int float_f2i(float_bits f)
{
    /*The biggest float number is 0 11111110 11111111111111111111111*/
    unsigned sign = f >> 31;
    unsigned exp = f >> 23 & 0xFF;
    unsigned frac = f & 0x7FFFFF;
    unsigned Bias = 0x7F;
    unsigned num, E, M;
    if (exp < Bias)
    {
        /*less than 1*/
        num = 0;
    }
    else if (exp >= 31 + Bias)
    {
        /*overflow*/
        num = 0x80000000;
    }
    else
    {
        E = exp - Bias;
        M = frac | 0x800000;
        if (E > 23)
            num = M << (E - 23);
        else
            num = M >> (23 - E);
    }
    return sign ? -num : num;
}

2.97

It is so hard!!!

相关标签: CSAPP