C ++ 17中的算术溢出

时间:2018-10-15 15:11:30

标签: c++ x86 g++ clang language-lawyer

  1. 每个C ++ 17是否为uint8_tuint16_tuint32_tuint64_t定义了算术溢出?如果是,定义的行为是什么(高度赞赏C ++标准的摘录)
  2. 每个C ++ 17是否为int8_tint16_tint32_tint64_t定义了算术溢出? (高度赞赏C ++标准的摘录)
  3. 如果以上任何一项或全部是特定于实现的,那么g ++和clang的定义是什么?
  4. 如果它是特定于体系结构的(如Havenard所指出的),那么我的问题仅针对x86(-64)。
  5. 如果我执行较小的unsigned int-较大的unsigned int,它定义明确了怎么办?

我看到这个post的第一个答案提到我的问题#1,它是用C标准定义的,尽管他没有引用它,而且我也找不到关于C ++标准的任何东西。

=================

更新1:

消除了每个ach的“下溢”,因为它是错误的术语(感谢@ach)。添加了#5,以表达我真正的意思是“下溢”(不正确)

1 个答案:

答案 0 :(得分:6)

为了创建规范,下面是一些规范性规范(引自最新的C ++草案):

  • 无符号整数不会溢出:请参见6.7.1:
  

无符号整数应服从2n模算术定律,其中n   是该特定值的值表示形式中的位数   整数的大小。 (44)这意味着无符号算术不   溢出,因为结果无法用结果表示   无符号整数类型以大一的形式取模   比可以由结果表示的最大值   无符号整数类型。

  • 未定义带符号整数的上溢/下溢:请参见7.1.4:
  

如果在对表达式求值时,结果不是   数学定义的或不在可表示的值范围内   它的类型,行为是不确定的。

顺便说一句,它们都不是特定于实现的,编译器会积极利用上溢/下溢进行优化。例如,如以下代码段所示:

void a();
void b();

void foo(int k) {
    int z = k+1;
    if (z < k) {
        a();
    } else {
        b();
    }
}

https://gcc.godbolt.org/z/0re-nM-消除了分支,即使在实际平台上由于模2表示,z实际上可能比k小。