type
date
slug
summary
status
tags
category
password
Last edited time
Jan 2, 2024 06:23 AM
icon
**2.59
题目
编写一个C表达式,它生成一个字,由x的最低有效字节和y中剩下的字节组成。对于运算数x=
0x89ABCDEE
和y=0x76543210
,就得到0x765432EE
解答
**2.60
题目
假设我们将一个w位的字中的字节从0(最低位)到wu/8-1(最高位》编号。写出下面C函数的代码,它会返回一个无符号值,其中参数x的字节主被替换成字节b:
unsigned replace_byte(unsigned x, int i, unsigned cha rb)
以下示例,说明了这个函数该如何工作:
replace_byte (0x12345678, 2, OxAB) -> 0x12A5678
replace_byte(0x12345678, 0, 0xAB) - 0x123456AB
解答
**2.67
题目
给你一个任务,编写一个过程int_ size_ is_ 32(), 当在一个int是32位的机器上运行时,该程序产生1,而其他情况则产生0。不允许使用sizeof运算符。下面是开始时的尝试:
当在SUN SPARC这样的32位机器上编译并运行时,这个过程返回的却是0。下面的编译器
信息给了我们一个问题的指示:
warning: left shift count >= width of type
A:我们的代码在哪个方面没有遵守C语言标准?
B:修改代码,使得它在int至少为32位的任何机器上都能正确地运行。
C:修改代码,使得它在int至少为16 位的任何机器上都能正确地运行。
解答
A:对变量beyond_msb进行左移的操作数32大于或等于该变量的宽度,即在单次连续的移位操作中不应直接达到变量的宽度,而应使用变量来隔断;
B:
C:
*2.71
题目
你刚刚开始在一家公司工作,他们要实现一组过程来操作一个数据结构,要将4个有符号字节封装成一个32位
unsigned
。一个字中的字节从0(最低有效字节)编号到3(最高有效字节)。分配给你的任务是:为一个使用补码运算和算术右移的机器编写一个具有如下原型的函数:
也就是说,函数会抽取出指定的字节,再把它符号扩展为一个32位
int
。你的前任(因为水平不够高而被解雇了)编写了下面的代码:
A:这段代码错在哪里?
B:给出函数的正确实现,只能使用左右移位和一个减法
解答
A:没有对抽取出的制定字节进行符号拓展
B:
可以先将
word
转化为有符号整数,然后根据指定的字节左移到最高、再右移到最低,自动进行符号拓展。**2.72
题目
给你一个任务,写一个函数,将整数
val
复制到缓冲区buf
中,但是只有当缓冲区中有足够可用的空间时,才执行复制。你写的代码如下:
这段代码使用了库函数
memcpy
。虽然在这里用这个函数有点刻意,因为我们只是想复制一个int
,但是它说明了一种复制较大数据结构的常见方法。你仔细地测试了这段代码后发现,哪怕
maxbytes
很小的时候,它也能把值复制到缓冲区中。A:解释为什么代码中的条件测试总是成功。提示:
sizeof
运算符返回类型为size
B:你该如何重写这个条件测试,使之工作正确
解答
A:
sizeof
运算符返回类型size
是无符号整数,因此表达式maxbytes - sizeof(val)
计算的结果也是一个无符号整数,总是非负的。B:
*2.76
题目
库函数calloc有如下声明:
void *calloc(size_t nmemb, size_t size);
”函数calloc为一个数组分配内存,该数组有nmemb个元素,每个元素为size字 节。内存设置为0。如果nmenb或size为0,则calloc返回NULL。” ——库文档
编写calloc的实现,通过调用malloc执行分配,调用memset将内存设置为0。你的代码应该没有任何由算术溢出引起的漏洞,且无论数据类型size_t用多少位表示,代码都应该正常工作。
作为参考,函数malloc和memset声明如下:
void *malloc (size_t size);
void *memset (void *s, int c, size_t n);
解答
**2.77
题目
假设我们有一个任务:生成一段代码,将整数变量x乘以不同的常数因子K。为了提高效率,我们想只使用+、-和<<运算。
对于下列K的值,写出执行乘法运算的C表达式,每个表达式中最多使用3个运算。
A. K=17
B. K=-7
C. K=60
D. K= -112
解答
*2.82
题目
我们在一个int类型值为32位的机器上运行程序。这些值以补码形式表示,而且它们都是算术右移的。unsigned类型的值也是32位的。
我们产生随机数x和y,并且把它们转换成无符号数,显示如下:
对于下列每个C表达式,你要指出表达式是否总是为1。如果它总是为1,那么请描述其中的数学原理。否则,列举出一个使它为0的参数示例。
A:
(x<y)==(-x>-y)
B:
((x+y)<<4)+y-x == 17*y+15*x
C:
~x+~y+1==~(x+y)
D:
(ux-uy) == - (unsigned) (y-x)
E:
((x>>2)<<2) <= x
解答
A:false。当x=TMIN时,-x=TMIN,因此
(-x>-y)
为假;B:false。取x=TMAX/16+1,y=1,可知
(17*y+15*x)
不会发生整数溢出,但((x+y)<<4)
会发生溢出;C:true。
~x+~y+1 = (-x)+(-y)-1 = -(x+y)-1 = ~(x+y)
D:true。无符号整数和有符号整数的位级运算没有差别,因此
(ux-uy) = (unsigned)x - (unsigned)y = (unsigned)(x-y) = - (unsigned) (y-x)
E:true。x为有符号整数,右移时高位补符号位、左移时低位补0,因此表达式执行后x的低2位变为0。若x为正数,其值变小;若x为负数,其绝对值变大,值变小。
*2.85
题目
给定一个浮点格式,有k位指数和n位小数,对于下列数,写出阶码E、尾数M、小数f和值V的公式。另外,请描述其位表示。
A:数7.0。
B:能够被准确描述的最大奇整数。
C:最小的规格化数的倒数。
解答
k位指数和n位小数,则Bias=,
对B,准确描述意味着不能发生舍入,因此阶码最大值为小数宽度n;
对C,最小规格化数为,其倒数为
ㅤ | E | M | f | V | 位级表示(s) | 位级表示(exp) | 位级表示(frac) |
A | 2 | 1.11 | 0.11 | 7.0 | 0 | 10…01 | 110…0 |
B | n | 1.11…1 | 0.11…1 | 0 | 111…1 | ||
C | 1.0 | 0.0 | 0 | 01…11 | 0...0 |
*2.87
题目
2008 版IEEE浮点标准,即 IEEE754-2008,包含了一种16位的“半精度”浮点格式。它最初是由计算机图形公司设计的,其存储的数据所需的动态范围要高于16位整数可获得的范围。这种格式具有1个符号位、5个阶码位(k=5)和10个小数位(n=10)。阶码偏置值:
对于每个给定的数,填写下表,其中,每一列具有如下指示说明:
Hex:描述编码形式的4个十六进制数字。
M:尾数的值。这应该是一个形如或 的数,其中是一个整数,而是 2 的整数幂。例如:0、、.
E:阶码的整数值。
V:所表示的数值。使用或者 ,其中和都是整数
D:(可能近似的)数值,用
printf
的格式规范%f
打印。举一个例子,为了表示数,我们有 。因此这个数的阶码字段为 (十进制值 15 − 1 = 14),尾数字段为,得到一个十六进制的表示。其数值为 0.875。
标记为“一”的条目不用填写。
描述 | Hex | M | E | V | D |
-0 | ㅤ | ㅤ | ㅤ | -0 | -0.0 |
最小的>2的值 | ㅤ | ㅤ | ㅤ | ㅤ | ㅤ |
512 | ㅤ | ㅤ | ㅤ | 512 | 512.0 |
最大的非规格化数 | ㅤ | ㅤ | ㅤ | ㅤ | ㅤ |
-∞ | ㅤ | —— | —— | -∞ | -∞ |
十六进制表示为0x3BB0的数 | 3BB0 | ㅤ | ㅤ | ㅤ | ㅤ |
解答
描述 | Hex | M | E | V | D |
-0 | 8000 | 0 | 0 | -0 | -0.0 |
最小的>2的值 | 4001 | 1 | 1.000977 | ||
512 | 6000 | 1 | 9 | 512 | 512.0 |
最大的非规格化数 | 03FF | -15 | 0.000015 | ||
-∞ | FC00 | —— | —— | -∞ | -∞ |
0x3BB0 | 3BB0 | -1 | 0.960938 |
*2.89
题目
我们在一个int类型为32位补码表示的机器上运行程序。float类型的值使用32位IEEE格式,而double类型的值使用64位IEEE格式。
我们产生随机整数x、y和z,并且把它们转换成double类型的值:
对于下列的每个C表达式,你要指出表达式是否总是为1。如果它总是为1,描述其中的数学原理。否则,列举出使它为0的参数的例子。
请注意,不能使用IA32机器运行GCC来测试你的答案,因为对于float 和 double,它使用的都是80位的扩展精度表示。
A:
(float)x == (float) dx
B:
dx-dy == (double) (x-y)
C:
(dx+dy) + dz == dx+ (dy+dz)
D:
(dx*dy) *dz == dx* (dy*dz)
E:
dx/dx == dz/dz
解答
A:true。int到double类型的转换不会丢失数据,而二者向float转换时数据丢失的情况也是一致的。
B:false。当y取INT_MIN时,
(x-y)
发生整数溢出,但dx-dy
不会发生溢出。C:true。double加法满足结合律。
D:true。double的乘法满足结合律。
E:false。当dx≠0而dz=0时,
dz/dz
会产生NaN结果。*2.90
题目
分配给你一个任务,编写一个C函数来计算的浮点表示。你意识到完成这个任务的最好方法是直接创建结果的IEEE单精度表示。当太小时,你的程序将返回0.0。当x太大时,它会返回 +∞。
填写下列代码的空白部分,以计算出正确的结果。假设函数u2f返回的浮点值与它的无符号参数有相同的位表示。
解答
- 作者:Antony_Zhang
- 链接:https://antonyzhang.cn/article/csapp-chapter2
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。