我正在研究二进制数的教程。我想知道一段时间的原因是为什么所有整数最大值和最小值都接触。例如,对于无符号字节255 + 1 = 0和0 - 1 = 255.我理解所有进入它的二进制数学,但为什么决定让它们以这种方式工作而不是直线数字给出一个极端事件被破坏时出错?
答案 0 :(得分:7)
由于您的示例是无符号的,我认为可以将范围限制为无符号类型。
允许包装很有用。例如,它允许您(和编译器)始终重新排序(和常数折叠)一系列加法和减法。如果语言需要陷阱,即使像x + 3 - 1
这样的东西也无法优化到x + 2
,因为它会改变表达式陷阱的条件。环绕也可以更好地与位操作混合,将无符号数解释为位向量,如果有陷阱则没有意义。这特别适用于移位,但加法,减法和偶数乘法在bitvectors上也有意义,并且与通常的按位运算有效结合。
允许换行时得到的代数结构,Z / 2 k Z,相当不错(也许不如模数的模数好,但是这会与比特矢量解释相互影响很大,并且它不会#39; t匹配典型的硬件)并且众所周知,所以它不会像任何特别意外或奇怪的事情发生,它不像包装结果是一个无用的随意"结果
当然,在几乎所有操作之后测试进位标志(或任何可能需要的标志)也会产生很大的直接开销。
陷入"无符号溢出"既昂贵又不受欢迎,至少如果它是默认行为。
答案 1 :(得分:0)
为什么不"在违反极端情况时给出错误"?
错误处理是软件开发中最难的事情之一。当发生错误时,可能需要许多软件来执行此操作:
Hey user, you have just tried to add 1 to this variable, which is already too big. Stop that!
一样 - 通常没有向用户显示的上下文,这将有任何帮助。正确的做法取决于您的代码。因此像C这样的通用编程语言并不想通过提供任何强制行为来限制您。
相反,C提供了两个指导原则:
unsigned int
或uint8_t
或(通常)char
等无符号类型,它会提供无声环绕,以获得最佳效果。int
这样的签名类型 - 它提供了"未定义的行为",这使得可以以非常有限的方式选择",溢出会发生什么
-ftrapv
,则-fwrapv
,则无声环绕
这里的想法是你(程序员)应该考虑检查溢出值得做什么,以及如何从溢出中恢复(如果语言提供了标准的错误处理机制,它会拒绝你是后者)。这种方法具有最大的灵活性,(可能)最大的性能,并且(通常)最难做到 - 这符合C的理念。