Precheck 1:C语言与数值表示¶
概念介绍¶
由于计算机内部通常使用二进制,而我们人类倾向于使用十进制,我们提出了一些表示方案,以便在人类概念的数字和计算机之间轻松转换。以下是一些最常见的表示方式:
无符号数¶
如果我们有一个 \(n\) 位无符号数字 \(d_{n-1}d_{n-2}\cdots d_0\),基数(或进制)为 \(r\),则该数字的值为:
$$
\sum_{i=0}^{n-1} r^i d_i,
$$
这相当于将十进制的“十位”“百位”换成了 \(r\) 的幂次位。对于三种常见进制:二进制、十进制和十六进制,我们将 \(r\) 分别设为 2、10 和 16。
有符号数¶
无符号二进制数可表示自然数,但许多计算需要负数。为此,使用了多种方案来表示有符号数。以下是两种常见的方案:
补码¶
-
一个 \(n\) 位补码的数值可表示为:
$$ \sum_{i=0}^{n-2} 2^i d_i \;-\; 2^{n-1}\,d_{n-1}. $$ -
负数的最高有效位(MSB)为 1。将 \(d_{n-1}=1\) 代入上式,得到:
$$ \sum_{i=0}^{n-2} 2^i d_i \;-\; 2^{n-1}. $$ - 正数的 MSB 为 0。将 \(d_{n-1}=0\) 代入,得到:
$$ \sum_{i=0}^{n-2} 2^i d_i, $$
与无符号数完全相同。 - 要取反(求相反数):对所有位取反后再加 1。
- 加法运算与无符号数相同。
- 只有一个零,表示为 `0b0`。
移码¶
- 将数值线性平移,使得要表示的最小数值对应二进制 `0...0`。
- 若要得到实际数值,则将表示当作无符号数读取,再加上偏移值。
- 可根据需求选择任意偏移。对于 \(N\) 位,为了对称地表示负数和正数,常用的偏移为
$$ -(2^{N-1}-1). $$
数值表示¶
-
在不同的上下文中,相同的比特序列可能表示不同的内容。
答案
正确。相同的比特在完全相同的情况下可以有多种不同的解释!这些比特可以表示无符号数、有符号数,甚至在我们之后将要学习的内容中,还可以表示一个程序。关键在于对它的解释是否达成了一致。
-
当用补码对两个符号相反的数进行加法时,可能会发生溢出。
答案
错误。 溢出错误只会在加法的正确结果超出范围 \([-(2^{n-1}), \quad 2^{n-1} - 1]\) 时发生。给符号相反的数相加不会导致结果超出这个范围。
-
如果将一个 \(N\) 位的补码按无符号数解释,那么负数会被解释为小于正数的值。
答案
错误。在补码表示法中,负数的最高有效位(MSB)总是 1。这意味着每一个负数在转换为无符号数时,其值都会比所有正数更大。
-
如果将一个 \(N\) 位的移码按无符号数解释(假设存在负数时的偏移量),那么负数会被解释为小于正数的值。
答案
正确。在移码表示法中,我们通过给无符号数加上一个偏移值来表示数值。无论我们如何“平移”可表示值的范围,负数在转换为无符号数时,总是比正数小。这一点不同于补码(见上文说明)。
-
我们可以在给定的数值表示格式(无符号、偏移和补码)中表示分数和小数。
答案
错误。我们目前的表示格式有一个主要的限制:只能表示整数并对整数进行运算。要想成功表示小数以及超出当前范围的极大数值,我们需要另一种表示格式。
C 语言¶
-
声明字符数组的正确方式是
char[] array。答案
错误。正确的写法是
char array[]。 -
C 是按值传递语言。
答案
正确。如果你想传递引用(reference),应该使用指针。