奇怪的整数溢出逻辑

abe*_*ier 1 c++ integer-arithmetic

对于下面的代码我得到溢出但遗憾的是我似乎无法理解为什么.

std::int8_t smallValue         = -1;
unsigned int value             = 500;
std::uint8_t anotherSmallValue = 1;

auto test = smallValue * value * anotherSmallValue;
Run Code Online (Sandbox Code Playgroud)

之后test是一个非常大的价值.

有人可以解释,这里发生了什么?

For*_*veR 6

结果类型将在unsigned int 这里测试.smallValue * value smallValue将被转换为无符号,所以这个表达式是(unsigned)-1 * 500.但是,如果你编译这段代码-Wsign-conversion- 编译器告诉你,你做了坏事.链接


Dan*_*aum 5

当编译器看到时smallValue * value,它必须根据输入数据类型signed(8位)和unsigned int(通常为16位或32位)决定结果的数据类型.C++的规则规定在这种情况下,结果将是无符号的.因此,价值smallValue * value不能-500像你期望的那样; 相反,该值-500被解释为POSITIVE数字.

此外,您在这里将8位值乘以通常为16位或32位的值.在这种情况下,C++的规则规定较小的存储值将首先转换为与较大的存储值相同的大小; 所以在这种情况下,结果smallValue * value确实足够大,可以存储多个数量级500.

继续乘以无符号数量anotherSmallValue(= 1)会导致另一个unsigned具有相同的值.

因为您正在使用auto,因此推断出返回类型unsigned.

简单地通过回退到signed(例如,将值定义testint,而不是auto,将依次将整个操作的结果转换回signed值,而不在内部更改位;然后将正确显示-500,正如你所期望的那样;然而,正如其他海报所指出的那样,这在理论上是相当危险的,因为它在技术上并不能保证工作,尽管它通常会以这种方式与今天的编译器一起工作.