在下面的代码中,我测试了哪种形式的溢出会导致UB,以及导致UB的原因constexpr
上下文中的硬错误:
#include <cstdint>
#include <limits>
using T = int8_t;
int main() {
constexpr bool b = []{
T x = std::numeric_limits<T>::max();
++x; // GCC: UB, Clang: no UB
// x += 1;
// x = x + 1;
return (x > std::numeric_limits<T>::max());
}();
return b;
}
预增量给出一个错误(如我所料)的gcc,而不是clang。
更奇怪的是,标准说++x
和x += 1
是一样的,但是使用它在gcc(和clang)上没有更多的错误。
进一步x += 1
应与x = x + 1
相同,因此rhs被提升为int
,结果被隐式转换。所以,这应该是新的UB。
所以,问题是,这三个语句中的哪一个真的应该是UB(我认为只有++x
),哪个编译器是正确的?
[expr.pre.incr]/1
表达式++x等价于x+=1。
[expr.ass]/6
E1 op= E2形式的表达式的行为等价于E1 = E1 op E2,只是E1只求值一次。
但是x = x + 1
不是UB(整数提升和窄化整数转换),所以原来是格式良好的。因此,GCC是错误的。