C++20要求使用二进制补码的影响

18
C++20将规定有符号整型必须使用二进制补码。鉴于(几乎?)每个实现当前都使用二进制补码,这似乎不是一个很大的变化。
但我想知道这个变化是否会将一些“未定义行为”转变为“实现定义”甚至“已定义”。
考虑绝对值函数std::abs(int)及其某些重载。 C++标准通过引用C标准来包含此函数,后者指出如果结果无法表示,则行为是未定义的。
在二进制补码中,不存在INT_MIN的正数对应项:
abs(INT_MIN) == -INT_MIN == undefined behavior

在符号数表示法中,有:

-INT_MIN == INT_MAX

因此,abs() 的一些未定义行为似乎是合理的。
一旦需要使用二进制补码,abs(INT_MIN) 的行为似乎可以被完全指定或至少是实现定义,而不会涉及向后兼容性的问题。但我没有看到任何这样的变化提议。
我唯一看到的缺点是C++标准需要明确指定abs(),而不是引用C标准对abs()的描述。(据我所知,C并不强制要求使用二进制补码。)
这只是委员会没有优先考虑还是仍有原因不能利用二进制补码强制规定提供的简化和确定性?

一则说明:C23版本现在不再支持除了二进制补码以外的任何有符号整数表示。参考链接:https://en.cppreference.com/w/c/23 - Vineet
2个回答

18
委员会考虑的具体问题之一是如何处理-INT_MIN,投票结果如下:
加法/减法/乘法和-INT_MIN溢出目前是未定义行为,应该改为: 4:环绕 6:环绕或陷阱 5:中间值是数学整数 14:现状(保持未定义行为)
人们明确考虑过并认为最好的选择是保持它的未定义行为。
为了澄清“中间值是数学整数”,论文的另一部分澄清了这意味着(int)a + (int)b > INT_MAX可能为真。
请注意,如果实现者选择这样做,它们可以自由定义这些情况的特定行为。我不知道他们中是否有任何人这样做。

评论不适合进行长时间的讨论;此对话已被移至聊天室 - sideshowbarker

3
C89标准委员会故意避免在现实情况下制定“质量实现应该”做的任何判断。已发布的《解释》表明,他们预计实现将在超出标准要求的情况下有用地运行(并且在整数溢出的情况下,甚至记录了一些非常具体的期望),但由于某种原因,委员会故意避免在标准本身中说这样的话。
当后来的C或C ++委员会添加新功能时,他们愿意考虑可能在一些平台上支持而在其他平台上不支持的可能性,但几乎从来没有努力重新审视是否应该识别许多实现会以相同的有用和一致的方式处理代码的情况,即使标准没有强制要求,并提供程序可以测试实现是否支持这种行为的手段,拒绝在不支持它的上面编译,并在支持它的上面定义行为。
净效果是像这样的语句:unsigned mul_mod_65536(unsigned short x, unsigned short y) { return (x*y) & 0xFFFFu; } 可能会任意干扰调用代码的行为,如果 x*y 的算术值介于 INT_MAX+1uUINT_MAX 之间,即使那是标准的作者说他们预计大多数实现将一致处理的情况。最近的标准已经消除了C89作者期望某些实现可能会奇怪处理上述函数的主要原因,但这并不意味着实现没有决定以C89作者永远无法想象和不会知道的方式奇怪地对待它。

这个例子不是更多地涉及到整数提升不能保持有符号性,而不是有符号整数实现问题吗? - Spencer
@seupercat同意,除了进一步说分数变为零的事实“排除”了保留整数提升中符号的原因。 - Spencer
消失的不是使用现有类型时需要现有推广规则的需求,而是在所有定义行为一致的情况下,对有符号和无符号数学进行不同处理的原因。 - supercat
因此,改变现有的整数提升规则的一个理由已经消失。 - Spencer
@Spencer:有任何合理理由偏离常规实践的实现比例已经降至零,但这并不意味着偏离常规实践的实现比例已经降至零。 - supercat
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接