C ++ 20的分支需要二进制补码

时间:2019-08-05 17:20:55

标签: c++ undefined-behavior twos-complement c++20

C ++ 20将指定signed integral types must use two's complement。鉴于(实际上?)每个实现当前都使用二进制补码,这似乎不是一个很大的改变。

但是我想知道此更改是否会将某些“未定义的行为”转变为“实现定义”甚至“定义”。

考虑绝对值函数std::abs(int)及其一些重载。 C ++标准通过引用C标准包括此功能,该标准表示如果无法表示结果,则行为是不确定的。

以2的补码形式,没有INT_MIN的正面对应物:

abs(INT_MIN) == -INT_MIN == undefined behavior

在符号幅度表示中,有:

-INT_MIN == INT_MAX

因此,abs()被留下一些未定义的行为似乎是合理的。

一旦需要用二进制补码,似乎可以完全指定abs(INT_MIN)的行为,或者至少定义实现,而没有任何向后兼容的问题。但是我看不到有任何提议的改变。

我看到的唯一缺点是C ++标准将需要显式指定abs(),而不是引用C标准对abs()的描述。 (据我所知,C并不要求补码。)

这是否不是委员会的优先事项,还是有理由不利用两国补编任务规定所提供的简化和确定性?

2 个答案:

答案 0 :(得分:10)

委员会考虑的specific questions之一是-INT_MIN的处理方法,该民意调查的结果是:

  

加/减/乘和-INT_MIN溢出是当前未定义的行为,它应该是:

     

4:包装
  6:包裹或诱捕
  5:中间值是数学整数
  14:现状(仍然是未定义的行为)

对此进行了明确考虑,人们认为最好的选择是保持其未定义的行为。

要澄清“中间值是数学整数”,论文的另一部分澄清了这意味着(int)a + (int)b > INT_MAX可能是正确的。


请注意,在这些情况下,实现者可以选择自由定义特定行为。我不知道他们有没有。

答案 1 :(得分:-1)

编写C89的委员会故意避免对质量实现在可行时“应该”做的事情做出任何判断。公布的基本原理表明,他们希望实施在超出标准要求的情况下有用(并且在整数溢出的情况下,甚至记录一些非常具体的期望),但是出于任何原因,委员会都故意避免在标准内说这些话。本身。

后来的C或C ++委员会增加了新功能时,他们愿意考虑它们在某些平台上可能受支持而在另一些平台上不受支持的可能性,但是几乎从未做出任何努力来重新审视标准是否应承认的问题。即使标准没有施加任何要求,许多实现仍将以相同有用且一致的方式处理代码的情况,并提供了一种程序可以用来测试实现是否支持这种行为,拒绝在不支持这种行为的情况下进行编译的方法,并已经定义了行为。

最终结果是,如果unsigned mul_mod_65536(unsigned short x, unsigned short y) { return (x*y) & 0xFFFFu; }的算术值在x*yINT_MAX+1u之间,则UINT_MAX可能会任意破坏调用代码的行为,即使该标准的作者表示,他们希望大多数实现能够一致地对其进行处理。最新标准消除了C89作者原本希望某些实现可能奇怪地处理上述功能的主要原因,但这并不意味着实现并未决定以C89作者从未拥有的方式对其进行奇怪的对待。想像的,永远不会有意地允许。