CSAPP 第三版 第二章 作业
自己做的 仅供参考 可能出现错误
发现几乎网上相关 -1 均表示为~0 不知道为啥23333
注:2.65 2.66 2.73 2.75 2.80 2.95 2.96 2.97 mark一下
略
int is_little_edian()
{
int n = 0xcd23ff;
int ch = *(unsigned char *)&n;
return ch == 0xff;
}
备注:
开始的时候用的是*(char * ),结果输出ch了是0xffff,想了想应该是因为先取出ff然后char是有符号的,按有符号的规则进行扩展扩展到32位于是在ff前补充11111111(即ff),所以不能用char应该用unsigned char来代替
开始看得有点懵,后来才知道最低有效字节是LSB啊,换了个说法……
不过看例子还是能猜到的
(x & 0xFF) | (y & ~0xFF)
unsigned replace_byte(unsigned x, int i, unsigned char b)
{
i <<= 3;
b <<= i;
return b | (x & ~(0xFF << i));
}
题目以为要判断四个条件同时成立,还在想说第一个条件不应该隶属于第三个条件,第二个条件不应该隶属于第四个条件么……emmm发现是我想多了,题目不难,我的答案里并没有对int的长度作出假设(没有假设int为4字节)
> A. !(~x);
> B. !x;
> C. !~((-1 << 8) | x);
> D. !(x >> ((sizeof(x) << 3) - 8));
默认一字节=8位
看了网上好多答案,发现可能是题目不一样,下面是我的书的题目
C.x的最低有效字节中的位都等于1
D.x的最高有效字节中的位都等于0
int int_shifts_are_arithmetic()
{
return !(~(-1 >> 1));
}
unsigned sr1(unsigned x, int k)
{
/* Perform shift arithmetically */
unsigned xsra = (int)x >> k;
return xsra & (-1 << (sizeof(int) * 8 - k));
}
int sra(int x, int k)
{
/* Perform shift logically */
int xsrl = (unsigned)x >> k;
int m = x & (0x1 << sizeof(int) * 8 - 1);
return xsrl + (((!m) + -1) << (sizeof(int) * 8 - k));
}
/* Return 1 when any odd bit of x equals 1; 0 otherwise.
Assume w=32 */
int any_odd_one(unsigned x)
{
return !~(x & 0x55555555 | 0xaaaaaaaa);
}
这道题琢磨了挺久,先把一半的数与另一半的数异或,若恰巧异或结果为0(0,0:这种情况无1不计数;0,1或1,0:这种情况计数为1留到下一轮;1,1:偶数个异或为0,就不考虑了,奇/偶数个+偶数个还是奇/偶数个)
/* Return 1 when x contains an odd number of 1s; 0 otherwise
Assume w=32 */
int odd_ones(unsigned x)
{
x ^= (x >> 16);
x ^= (x >> 8);
x ^= (x >> 4);
x ^= (x >> 2);
x ^= (x >> 1);
return !!(x & 0x1);
}
受到上一题的启发,同样每次折半或,将原来的数化为[0…111]位向量,然后右移一位加一就ok了
/* 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 >> 16);
x |= (x >> 8);
x |= (x >> 4);
x |= (x >> 2);
x |= (x >> 1);
return (x >> 1) + 0x1;
}
A. C语言的移位操作符规定移位数应小于机器字长,C语言并没有对大于等于机器字长的移位要求做出明确要求与处理方式
B.
/* The following code does not run properly on some machines */
int bad_int_size_is_32()
{
/* Set most significant bit (msb) of 32-bit word */
int set_msb = 1 << 31;
/* Shift past msb of 32-bit word */
int beyond_msb = set_msb << 1;
/* set_msb is nonzero when word size >= 32
beyond_msb is zero when word size <= 32 */
return set_msb && !beyond_msb;
}
C.
int bad_int_size_is_32()
{
/* Set most significant bit (msb) of 32-bit word */
int set_msb = 1 << 15 << 15 << 1;;
/* Shift past msb of 32-bit word */
int beyond_msb = set_msb << 1;
/* set_msb is nonzero when word size >= 32
beyond_msb is zero when word size <= 32 */
return set_msb && !beyond_msb;
}
/*
* Mask with least significant n bits set to 1
* Examples: n = 6 --> 0x3F, n = 17 -->0x1FFFF
* Assume 1 <= n <= w
*/
int lower_one_mask(int n)
{
return 1 << (n - 1) << 1;
}
/*
* Do rotating left shift. Assume 0 <= n < w
* Examples when x = 0x12345678 and w = 32:
* n=4 -> 0x 23456781, n=20 -> 0x67812345
*/
unsigned rotate_left(unsigned x, int n)
{
int t = 1 << ((sizeof(int) << 3) - 1);
int m = t >> n;
int sm = ((int)x & m) >> ((sizeof(int) << 3) - n - 1) >> 1;//防止括号里面超过w
return sm | (x << n);
}
/*
* Return 1 when x can be represented as an n-bit, 2's-complement
* number; 0 otherwise
* Assume 1 <= n <= w
*/
6.int fits_bits(int x, int n)
7.{
8. int t = x >> (n - 1);
9. return !(t && ~t);
}
A. 根据符号扩展的规则,如果该字节(MSB为符号位)为负数,则按要求应拓展为[111…]形式,而给出的bug代码中不能完成这个操作
B.
/* Declaration of data type where 4 bytes are packed
into an unsigned */
typedef unsigned packed_t;
/* Extract byte from word. Return as signed integer */
int xbyte(packed_t word, int bytenum)
{
int left = (sizeof(int) - 1 - bytenum) << 3;
int right = (sizeof(int) - 1) << 3;
return (unsigned)((int)word << left >> right);
}
A. sizeof(val)为unsigned,与maxbytes(int类型)运算时将全部转换为(unsigned)类型进行运算,于是maxbytes-sizeof(val) >= 0永真,故条件测试总是成功
B.
/* Copy integer into buffer if space is available */
/* WARNING: The following code is buggy */
void copy_int(int val, void *buf, int maxbytes)
{
if (maxbytes - (int)sizeof(val) >= 0)
{
memcpy(buf, (void *)&val, sizeof(val));
}
}
/* Addition that saturates to TMin or TMax */
int saturating_add(int x, int y)
{
int TMin = 1 << ((sizeof(int) << 3) - 1) << 1;
int TMax = TMin - 1;
int sum = x + y;
int m = (x & TMin) & (y & TMin) & !(sum & TMin);
int n = !(x & TMin) & !(y & TMin) & (sum & TMin);
(m && (sum = TMax)) || (n && (sum = TMin));
return sum;
}
/* Determine whether arguments can be substracted without overflow */
int tsub_ok(int x, int y)
{
int sum = x - y;
int neg_over = x < 0 && y > 0 && sum >= 0;
int pos_over = x >= 0 && y <= 0 && sum < 0;
return !neg_over && !pos_over;
}
//#include
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);
}
//void *malloc(size_t size);
//void *memset(void *s, int c, size_t n);
void *calloc(size_t nmemb, size_t size)
{
void *p;
if (nmemb == 0 || size == 0)
{
return NULL;
}
size_t goal = size * nmemb;
if (nmemb != goal / size)
{
return NULL;
}
p = malloc(goal);
if (p == NULL)
{
return NULL;
}
memset(p, 0, goal);
return p;
}
> A. x = x + (x << 4);
> B. x = x - (x >> 3);
> C. x = (x << 6) - (x << 2);
> D. x = (x << 4) - (x << 7);
/* Divide by power of 2. Assume 0 <= k < w-1 */
int divide_power2(int x, int k)
{
int bias = (x >> ((sizeof(int) << 3) - 1)) & ((1 << k) - 1);
return (x + bias) >> k;
}
int mul3div4(int x)
{
x += x << 1;
int bias = (x >> ((sizeof(int) << 3) - 1)) & ((1 << 2) - 1);
return (x + bias) >> 2;
}
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;
}
> A. (~0) << k;
> B. (~((~0) << (k + j))) & ((~0) << j);
> A.当x=Tmin,y=0时,该表达式为0;
> B.该表达式总为1,因为17 * x + 15 * y = 16 * (x + y) + y - x = (x + y) << 4 + y - x;
> C.该表达式总为1:由于~x = -x - 1, ~y = -y - 1,则~x + ~y + 1 = -x - 1 + (-y - 1) + 1 = -x - y - 1,而~(x + y) = -x - y - 1,故两式相等;
> D.该表达式总为1,因为无符号与有符号加减法位级表示相同并且最终都为unsigned类型,故相等;
> E.该表达式总为1,因为先右移再左移,最低位丢失或不丢失,故比移位前值不变或变小;
> A. Y/(2^k-1);
> B.
> ( a ).5/7;
> ( b ).2/5;
> ( c ).19/63;
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) == 0 && (uy << 1) == 0) || (sx && !sy) || (!sx && !sy && ux <= uy) || (sx && sy && ux >= uy);
}
> A. E = 2 - (2^(k - 1) - 1) = 3 - 2^(k - 1), M = 1 + f = 1 + (2^(-1) + 2^(-2)) = 9/4, f = 5/4, V=2^E * M 0|10..01|110...0;
> B. E = n, M = 1 + f = 2 - 2^(-n), f = 1 - 2^(-n), V = 2^E * M 0|1...1|1...1;
> C. E = -(1 - (2^(k - 1) -1)) = 2^(k - 1) - 2, M = 1 + f = 1 + 0 = 1, f = 0, V = 2^E * M = 2^(2^(k - 1) - 2) 0|11... 01|0...0;
> 最小的正非规格化数:
值:0|0...00|0|0...01| 十进制:E=1-bias=2-2^14=-16382,M=frac=2^(-63),故值为2^(-16445)= 3.645e-4951 ;
> 最小的正规格化数:
值:0|0...01|1|0...00| 十进制:E=e-bias=2-2^14=-16382,frac=0,M=1+frac=1,故值为2^(-16382)= 3.362e-4932 ;
> 最大的规格化数:
值:0|1...10|1|1...11| 十进制:E=e-bias=2^15-2-(2^14-1)=16383,frac=(2^(-1)+2^(-2)+...+2^(-63))=1-2^(-63),M=1+frac=2-2^(-63),故值为2^16383*(2-2^(-63))=1.190e+4932 ;
//%f默认保留6位小数!!!
> 0x8000 0 -14 -0 -0.0
> 0x4001 1025/1024 15 1025/512 2.001953
> 0x0200 1 9 512 512.0
> 0x03FF 1023/1024 -14 1023/(2^(-24)) 0.000061
> 0xFC00 - - -∞ -∞
> 0x3BB0 123/64 -1 123/128 0.960938
> 208 0|1110|1010 208
> -7/1024 1|0000|0111 -7/1024
> 5/2^17 0|0000|0001 1/2^10
> -2^12 1|1110|1111 -248
> 768 0|1111|0000 +∞
> A. 总为1,因为从int转换为double类型属于精确转换,则均转换为float时情况相同;
> B. 不总为1,x = TMIN, y = 1;
> C. 不总为1,x = 3.1415926, y = 1e300, z = -1e300;//浮点数加法不满足结合律
> D. 不总为1,x = 1e-308, y = 1e308, z = 9.7//浮点数乘法不满足结合律、分配率
> E. 不总为1,x = 1,y = 0
float fpwr2(int x)
{
/* Result exponent and fraction */
unsigned exp, frac;
unsigned u;
if (x < -149) {
/* Too small. Return 0.0 */
exp = 0;
frac = 0;
}
else if (x < -126) {
/* Denormalized result */
exp = 0;
frac = (1 << (149 + x));
}
else if (x < 128) {
/* Normalized result */
exp = x + 127;
frac = 0;
}
else
{
/* Too big. Return +0.0 */
exp = 255;
frac = 0;
}
/* Pack exp and frac into 32 bits */
u = exp << 23 | frac;
/* Return as float */
return u2f(u);
}
> A. 0|10000000|10010010000111111011010
> B. 11.001001001001...
> C. 第九位
/* Access bit_level representation floating_point number */
typedef unsigned float_bits;
/* Compute -f. If f is NaN, then return f. */
float_bits float_negate(float_bits f)
{
float_bits sign = f >> 31;
float_bits exp = (f >> 23) & 0xFF;
float_bits frac = f & 0x7FFFFF;
if (exp == 0xFF && frac != 0)
{
return f;
}
sign = (~sign);
return (sign << 31) | (exp << 23) | frac;
}
/* Access bit_level representation floating_point number */
typedef unsigned float_bits;
/* Compute |f|. If f is NaN, then return f. */
float_bits float_absval(float_bits f)
{
float_bits exp = (f >> 23) & 0xFF;
float_bits frac = f & 0x7FFFFF;
if (exp == 0xFF && frac != 0)
{
return f;
}
return (0 << 31) | (exp << 23) | frac;
}
/* Access bit_level representation floating_point number */
typedef unsigned float_bits;
/* Compute 2*f. If f is NaN, then return f. */
float_bits float_twice(float_bits f)
{
float_bits sign = f >> 31;
float_bits exp = (f >> 23) & 0xFF;
float_bits frac = f & 0x7FFFFF;
if (exp == 0xFF && frac != 0)
{
return f;
}
if (exp == 0)
{
if (!(frac >> 22))
{
frac = (frac << 1);
}
else
{
exp = 1;
frac = (frac << 1) & 0x7FFFFF;
}
}
else
{
exp++;
if (exp == 255)
{
frac = 0;
}
}
return (sign << 31) | (exp << 23) | frac;
}
/* Access bit_level representation floating_point number */
typedef unsigned float_bits;
/* Compute 0.5*f. If f is NaN, then return f. */
float_bits float_half(float_bits f)
{
float_bits sign = f >> 31;
float_bits exp = (f >> 23) & 0xFF;
float_bits frac = f & 0x7FFFFF;
if (exp == 0xFF)
{
return f;
}
unsigned condition = ((f & 0x3) == 0x3);
if (exp == 0)
{
frac = frac >> 1;
frac += condition;
}
else if(exp == 1)
{
exp = 0;
frac = (frac >> 1);
frac += condition;
frac |= 0x400000;
}
else
{
exp--;
}
return (sign << 31) | (exp << 23) | frac;
}
/* Access bit_level representation floating_point number */
typedef unsigned float_bits;
/*
* Compute (int) f.
* If conversion cause overflow overflow or f is NaN, return 0x80000000
*/
int float_f2i(float_bits f)
{
float_bits sign = f >> 31;
float_bits exp = (f >> 23) & 0xFF;
float_bits frac = f & 0x7FFFFF;
float_bits bias = 127;
float_bits num;
float_bits E, M;
if (exp < bias)
{
num = 0;
}
else if (exp >= 31 + bias)
{
num = 0x80000000;
}
else
{
E = exp - bias;
M = frac | 0x800000;
if (E > 23)
{
num = M << (E - 23);
}
else
{
num = M >> (23 - E);
}
}
return sign ? -(int)num : (int)num;
}
#include
/* Access bit_level representation floating_point number */
typedef unsigned float_bits;
/* Compute (float) i */
float_bits float_i2f(int i)
{
float_bits sign, exp, frac, num, E, M;
float_bits bias = 127;
if (i == 0)
{
return 0;
}
if (i == INT_MIN)
{
sign = 1;
exp = 31 + bias;
frac = 0;
return (sign << 31) | (exp << 23) | frac;
}
sign = i > 0 ? 0 : 1;
if (i < 0)
{
i = -i;
}
float_bits bits = 0;
float_bits ui = (float_bits)i;
while (ui > 0)
{
ui >>= 1;
++bits;
}
float_bits fbits = bits - 1;//2^fbits
exp = bias + fbits;
float_bits uux = (1 << (fbits - 1));
uux |= uux >> 1;
uux |= uux >> 2;
uux |= uux >> 4;
uux |= uux >> 8;
uux |= uux >> 16;
float_bits fb = uux & i;
if (fbits <= 23)
{
frac = fb << (23 - fbits);
}
else//无法精确表示
{
float_bits j = fbits - 23;
frac = fb >> j;
float_bits round_mid = 1 << (j - 1);
float_bits uuy = (1 << (j - 1));
uuy |= uuy >> 1;
uuy |= uuy >> 2;
uuy |= uuy >> 4;
uuy |= uuy >> 8;
uuy |= uuy >> 16;
float_bits round_part = fbits & uuy;
if (round_part > round_mid)
{
++frac;
}
else if (round_part == round_mid)
{
if (frac & 0x1)
{
++frac;
}
}
}
return (sign << 31) | (exp << 23) | frac;
}