2.55 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 #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 (int ));}void  show_pointer (void  *x)  {show_bytes((byte_pointer)&x,sizeof (void  *));}void  test_show_bytes (int  val)  {     int  ival=val;     float  fval=(float )ival;     int  *pval=&ival;     show_int(ival);     show_float(fval);     show_pointer(pval); }int  main ()  {     test_show_bytes(12345 );     return  0 ; }
 
小端法。
2.56 
1 2 3 4 5 6 7 8 9 10 11 12 100   64  00  00  00   00  00  c8 42   cc fd 61  00  00  00  00  00 -1   ff ff ff ff  00  00  80  bf  cc fd 61  00  00  00  00  00 0   00  00  00  00   00  00  00  00   cc fd 61  00  00  00  00  00 
 
一个有趣的现象是它们的指针都是相同的。
2.57 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 #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 (int ));}void  show_pointer (void  *x)  {show_bytes((byte_pointer)&x,sizeof (void  *));}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 ));}void  test_show_bytes (int  val)  {     int  ival=val;     float  fval=(float )ival;     int  *pval=&ival;     short  sval=(short )ival;     long  lval=(long )ival;     double  dval=(double )ival;     show_int(ival);     show_float(fval);     show_pointer(pval);     show_short(sval);     show_long(lval);     show_double(dval); }int  main ()  {     int  x;scanf ("%d" ,&x);     test_show_bytes(x);     return  0 ; }
 
2.58 
1 2 3 4 5 6 int  is_little_endian ()  {     int  a=1 ;     byte_pointer p=(byte_pointer)&a;     return  p[0 ]; }
 
2.59 
1 2 3 4 5 6 7 8 #include  <stdio.h>  int  main ()  {     int  a,b;scanf ("%x %x" ,&a,&b);     int  mask=0xff ;     printf ("%x\n" ,((a&mask)|(b&(~mask))));     return  0 ; }
 
2.60 
1 2 3 4 5 6 unsigned  replace_byte (unsigned  x,int  i,unsigned  char  b)  {     unsigned  char  *p=(unsigned  char  *)&x;     p[i]=b;     return  x; }
 
缺点是只适用于小端的机器。网上有一种普适的写法:
1 2 3 4 5 size_t  replace_byte (unsigned  x,int  i,unsigned  char  b)  {     size_t  mask=((unsigned )0xff )<<(i<<3 );     return  (x&(~mask))|(((unsigned )b)<<(i<<3 )); }
 
2.61 
1 2 3 4 !~x !x !~(x|~0xff ) !(x>>((sizeof (int )-1 )<<3 ))
 
2.62 
1 2 3 4 5 int  int_shifts_are_arithmetic ()  {     int  w=(sizeof (int ))<<3 ;     return  (INT_MIN)>>(w-1 )==-1 ; }
 
更好的做法:
1 2 3 4 5 int  int_shifts_are_arithmetic ()  { 	int  x=-1 ;     return  x==x>>3 ; }
 
2.63 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 unsigned  srl (unsigned  x,int  k)  {     unsigned  xsra=(int )x>>k;     int  w=8 *sizeof (int );     int  mask=(-1 )<<(w-k);     return  xsra&(~mask); }int  sra (int  x,int  k)  {     int  xsrl=(unsigned )x>>k;     int  w=8 *sizeof (int );     int  mask=(-1 )<<(w-k);     int  bit=x&(1 <<(w-1 ));     mask&=(!bit-1 );     return  xsrl|mask; }
 
2.64 
1 2 3 4 int  any_odd_one (unsigned  x)  {     return  !!(x&0xaaaaaaaa ); }
 
2.65 
1 2 3 4 5 6 7 8 int  odd_ones (unsigned  x) {     x^=x>>16 ;     x^=x>>8 ;     x^=x>>4 ;     x^=x>>2 ;     x^=x>>1 ;     return  x&1 ; }
 
没能想到。思路比较巧妙:最终 x 的最低位相当于是所有位异或起来的结果。
2.66 
1 2 3 4 5 6 7 8 int  leftmost_one (unsigned  x)  {   x |= x >> 1 ;   x |= x >> 2 ;   x |= x >> 4 ;   x |= x >> 8 ;   x |= x >> 16 ;   return  (x >> 1 ) + (x && 1 );	 }
 
同样巧妙:保证从第一次出现的 1 开始往后都是 1。然后右移再加 1 就是所要求的数了。
2.67 
A 
当 int 为 32 32 32   位时,有效的移位位数为 0 ∼ 31 0\sim31 0 ∼ 31  。代码中左移 32 32 32   位是不合法的。
B 
1 2 3 4 5 6 int  int_size_is_32 ()  {     int  set_msb=1 <<31 ;     int  beyond_msb=set_msb<<1 ;     return  set_msb&&!beyond_msb; }
 
C 
1 2 3 4 5 6 7 8 int  int_size_is_32_ng ()  {     int  set_msb=1 <<15 ;     set_msb=set_msb<<15 ;     set_msb=set_msb<<1 ;     int  beyond_msb=set_msb<<1 ;     return  set_msb&&!beyond_msb; }
 
2.68 
1 2 3 4 5 6 int  lower_one_mask (int  n)  {     int  mask=-1 ;     int  w=sizeof (int )<<3 ;     return  (unsigned )mask>>(w-n); }
 
2.69 
1 2 3 4 5 6 7 8 9 10 unsigned  rotate_left (unsigned  x,int  n)  {     unsigned  mask=-1 ;     int  w=sizeof (int )<<3 ;     mask<<=(w-n);     int  most=mask&x;     x<<=n;     most>>=(w-n);     return  most|x; }
 
先保留 x x x   的高 n n n   位,然后和 x x x   左移 n n n   位得到的数拼起来。当然这里其实不需要使用掩码:
1 2 3 4 5 6 unsigned  rotate_left (unsigned  x,int  n)  {     unsigned  w1=x<<n;     unsigned  w2=x>>((sizeof (int )<<3 )-n);     return  w1|w2; }
 
upd:以上两个做法都没有考虑到 n = 0 n=0 n = 0   的情况,改进如下:
1 2 3 4 5 6 7 unsigned  rotate_left (unsigned  x,int  n)  {     unsigned  w1=x<<n;     unsigned  w2=x>>1 ;     w2>>=((sizeof (int )<<3 )-n-1 );     return  w1|w2; }
 
2.70 
1 2 3 4 5 int  fits_bits (int  x,int  n)  {     x>>=(n-1 );     return  x==0 ||x==-1 ; }
 
一个性质是,能够被表示的数满足:若该数为非负数,则高 w − n + 1 w-n+1 w − n + 1   位均为 0 0 0   ,否则高 w − n + 1 w-n+1 w − n + 1   位均为 1 1 1  。
网上的写法:
1 2 3 4 5 int  fits_bits (int  x,int  n)  {     int  w=sizeof (int )<<3 ;     return  x==x<<(w-n)>>(w-n); }
 
相当于是剔除了多余的符号位。
2.71 
A 
未进行符号扩展。
B 
1 2 3 4 5 typedef  unsigned  packed_t ;int  xbyte (packed_t  word,int  bytenum)  {     return  ((int )(word<<((3 -bytenum)<<3 )))>>24 ; }
 
2.72 
A 
size_t 为无符号,所以这里出现了有符号向无符号的隐式转换。而一个无符号的数始终大于等于 0 0 0  ,所以条件测试总是成功。
B 
1 2 3 4 5 void  copy_int (int  val,void  *buf,int  maxbytes)  {     if (maxbytes>=sizeof (val))         memcpy (buf,(void *)&val,sizeof (val)); }
 
2.73 
1 2 3 4 5 6 7 8 9 10 int  saturating_add (int  x, int  y)  {   int  sum=x+y;   int  sig_mask=INT_MIN;      int  pos_over=!(x & sig_mask) && !(y & sig_mask) && (sum & sig_mask);   int  neg_over=(x & sig_mask) && (y & sig_mask) && !(sum & sig_mask);      pos_over && (sum = INT_MAX) || neg_over && (sum = INT_MIN);   return  sum; }
 
避开 if 的一个小 trick。
2.74 
1 2 3 4 5 6 7 8 int  tsub_ok (int  x,int  y)  {     int  w=(sizeof (int )<<3 )-1 ;     int  z=x-y;     int  pos_over=(x>>w)&&(!(y>>w))&&(!(z>>w));     int  neg_over=(!(x>>w))&&(y>>w)&&(z>>w);     return  !(pos_over||neg_over); }
 
2.75 
1 2 3 4 5 6 unsigned  unsigned_high_prod (unsigned  x,unsigned  y)  {     int  w=(sizeof (int )<<3 )-1 ;     int  a=x>>w,b=y>>w;     return  signed_high_prod(x,y)+a*y+b*x; }
 
2.76 
1 2 3 4 5 6 7 8 9 10 11 12 void  *calloc (size_t  nmemb,size_t  size)  {     if (!nmemb||!size) return  NULL ;     size_t  buf_size=nmemb*size;     if (buf_size/size==nmemb)     {         void  *p=malloc (buf_size);         if (p!=NULL ) memset (p,0 ,buf_size);         return  p;     }        return  NULL ; }
 
2.77 
A 
( x < < 4 ) + x (x<<4)+x ( x << 4 ) + x 
B 
x − ( x < < 3 ) x-(x<<3) x − ( x << 3 ) 
C 
( x < < 6 ) − ( x < < 2 ) (x<<6)-(x<<2) ( x << 6 ) − ( x << 2 ) 
D 
( x < < 4 ) − ( x < < 7 ) (x<<4)-(x<<7) ( x << 4 ) − ( x << 7 ) 
2.78 
1 2 3 4 5 6 int  divide_power2 (int  x,int  k)  {     int  w=(sizeof (int )<<3 );     (x>>(w-1 ))&&(x+=((1 <<k)-1 ));     return  x>>k; }
 
利用短路避免了使用 if 或乘法,但感觉没什么意义啊(×
2.79 
1 2 3 4 5 int  mul3div4 (int  x)  {     x=(x<<1 )+x;     return  (x+((1 <<2 )-1 )*(x<0 ))>>2 ;  }
 
感觉题目要求翻译的怪怪的。和下一题对比来看,这道题目应该是允许溢出的(?不过这里用了乘法和比较,还是不太好,不如直接看下一题。
2.80 
1 2 3 4 5 6 7 int  mul3div4 (int  x)  {     int  y=x;     int  w=sizeof (int )<<3 ;     (x>>(w-1 ))||(y+=3 );     return  x-(y>>2 ); }
 
一个小问题是 y+=3 仍然可能溢出,解决办法是对它进行判断,如果溢出则直接取减数为 y>>2+1 。
1 2 3 4 5 6 7 8 9 int  mul3div4 (int  x)  {     int  y=x;     int  w=sizeof (int )<<3 ;     (x>>(w-1 ))||(y+=3 );     int  ans=x-(y>>2 );     !(x>>(w-1 ))&&!((y-3 )>>(w-1 ))&&(y>>(w-1 ))&&(ans=x-((y-3 )>>2 )+1 );     return  ans; }
 
2.81 
A 
− 1 < < k -1<<k − 1 << k 
B 
( − 1 < < k ) ⊕ ( − 1 < < ( j + k ) ) (-1<<k)\oplus(-1<<(j+k)) ( − 1 << k ) ⊕ ( − 1 << ( j + k )) 
另一种方法是 ∼ ( − 1 < < k ) < < j \sim(-1<<k)<<j ∼ ( − 1 << k ) << j  。
2.82 
A 
错误
x = T M I N , y = 0 x=\mathrm{TMIN},y=0 x = TMIN , y = 0 
B 
正确
( ( x + y ) < < 4 ) + y − x = 16 ( x + y ) + y − x = 17 y + 15 x \begin{aligned}
&((x+y)<<4)+y-x\\
&=16(x+y)+y-x\\
&=17y+15x
\end{aligned}
  (( x + y ) << 4 ) + y − x = 16 ( x + y ) + y − x = 17 y + 15 x  
C 
正确
∼ x + ∼ y + 1 = − x − 1 − y − 1 + 1 = − ( x + y ) − 1 =   ( x + y ) \begin{aligned}
&\sim x+\sim y+1\\
&=-x-1-y-1+1\\
&=-(x+y)-1\\
&=~(x+y)
\end{aligned}
  ∼ x + ∼ y + 1 = − x − 1 − y − 1 + 1 = − ( x + y ) − 1 =   ( x + y )  
D 
正确
E 
正确
2.83 
A 
Y 2 k − 1 \dfrac{Y}{2^k-1} 2 k − 1 Y  
B 
a)  5 7 \dfrac{5}{7} 7 5  
b)  2 5 \dfrac{2}{5} 5 2  
c)  19 63 \dfrac{19}{63} 63 19  
2.84 
1 2 3 4 5 6 7 sx>sy|| (!sx&&!sy&&ux<=uy)|| (sx&&sy&&ux>=uy)|| (!(ux<<1 )&&!(uy<<1 ))
 
2.85 
 
阶码 
尾数 
小数 
值 
位表示 
 
 
A 
2 2 2  
7 4 \frac{7}{4} 4 7   
3 4 \frac{3}{4} 4 3   
7 7 7  
100…1 1100… 
 
B 
n n n  
2 − 1 2 n 2-\frac{1}{2^n} 2 − 2 n 1   
1 − 1 2 n 1-\frac{1}{2^n} 1 − 2 n 1   
2 n + 1 − 1 2^{n+1}-1 2 n + 1 − 1  
100…11…1 11…1 
 
C 
2 k − 1 − 2 2^{k-1}-2 2 k − 1 − 2  
1 1 1  
0 0 0  
2 2 k − 1 − 2 2^{2^{k-1}-2} 2 2 k − 1 − 2  
11…0 00…0 
 
 
2.86 
 
值 
十进制 
 
 
最小的正非规格化数 
2 − 16446 2^{-16446} 2 − 16446  
1.8 × 1 0 − 4951 1.8\times10^{-4951} 1.8 × 1 0 − 4951  
 
最小的正规格化数 
2 − 16382 2^{-16382} 2 − 16382  
3.4 × 1 0 − 4932 3.4\times10^{-4932} 3.4 × 1 0 − 4932  
 
最大的规格化数 
2 16384 − 2 16320 2^{16384}-2^{16320} 2 16384 − 2 16320  
1.2 × 1 0 4932 1.2\times10^{4932} 1.2 × 1 0 4932  
 
 
2.87 
 
Hex 
M 
E 
V 
D 
 
 
-0 
8000 
0 0 0  
− 14 -14 − 14  
− 0 -0 − 0  
− 0.0 -0.0 − 0.0  
 
最小的>2的值 
4001 
1025 1024 \frac{1025}{1024} 1024 1025   
1 1 1  
1025 512 \frac{1025}{512} 512 1025   
2.001953 2.001953 2.001953  
 
512 
6000 
1 1 1  
9 9 9  
512 512 512  
512.0 512.0 512.0  
 
最大的非规格化数 
03FF 
1023 1024 \frac{1023}{1024} 1024 1023   
− 14 -14 − 14  
1023 2 − 24 \frac{1023}{2^{-24}} 2 − 24 1023   
0.000061 0.000061 0.000061  
 
-∞ 
FC00 
— 
— 
− ∞ -∞ − ∞  
− ∞ -∞ − ∞  
 
十六进制表示为3BB0的数 
3BB0 
123 64 \frac{123}{64} 64 123   
− 1 -1 − 1  
123 128 \frac{123}{128} 128 123   
0.960938 0.960938 0.960938  
 
 
2.88 
1 2 3 4 5 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       +∞
 
2.89 
A 
正确。
int 向 double 转换不会损失精度,最终转成 float 的结果也一致。
B 
错误。
x = 0 , y = T M I N x=0,y=\mathrm{TMIN} x = 0 , y = TMIN 
C 
错误。
d x = 0.001 , d y = 1 0 300 , d z = − 1 0 300 dx=0.001,dy=10^{300},dz=-10^{300} d x = 0.001 , d y = 1 0 300 , d z = − 1 0 300 
D 
错误。
d x = 1.001 , d y = 1 0 300 , d z = 1 0 − 300 dx=1.001,dy=10^{300},dz=10^{-300} d x = 1.001 , d y = 1 0 300 , d z = 1 0 − 300 
E 
d x = 1 , d z = 0 dx=1,dz=0 d x = 1 , d z = 0 
2.90 
-149
0
0
-126
0
(1<<(149+x))
128
x+127
0
255
0
2.91 
A 
11.0010010000111111011011
B 
11.001(001)
C 
小数点后第九位
2.92 
1 2 3 4 5 6 7 8 9 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;     sign^=1 ;     return  (sign<<31 )|(exp <<23 )|frac; }
 
奇怪的是如果使用 float,NAN 符号位会被翻转。这与题目中给出的要求不吻合。(不知道是不是测试出了什么bug还是版本问题)
2.93 
1 2 3 4 5 6 7 8 9 10 typedef  unsigned  float_bits; float_bits float_absval (float_bits f)  {     unsigned  sign=f>>31 ;     unsigned  exp =f>>23 &0xff ;     unsigned  frac=f&0x7fffff ;     if (exp ==0xff &&frac) return  f;     sign=0 ;     return  (sign<<31 )|(exp <<23 )|frac;  }
 
2.94 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 float_bits float_twice (float_bits f)  {     unsigned  sign=f>>31 ;     unsigned  exp =f>>23 &0xff ;     unsigned  frac=f&0x7fffff ;     if (exp ==0xff &&frac!=0 ) return  f;     if (exp ==0 )     {         if (frac>>22 )         {             exp ++;             frac=(frac<<1 )&0x7fffff ;         }         else  frac=frac<<1 ;     }        else      {         if (exp <255 ) exp ++;         if (exp ==255 ) frac=0 ;     }     return  (sign<<31 )|(exp <<23 )|frac; }
 
剩下几道不想写了,感觉没什么意思,而且会有点麻烦(×