C 在方程内溢出

C overflows inside an equation?

本文关键字:溢出 方程内      更新时间:2023-10-16
a + b

我预期的那样将 255 溢出回 4,然后c / 2如我预期的那样给出 2。但是,为什么最后一个示例在评估相同的两个步骤时没有溢出呢?

我猜内部计算值存储了更多位,然后在执行作业时仅截断为 8 位。在这种情况下,极限在哪里,它必须在某个时候溢出?

uint8_t a = 250;
uint8_t b = 10;
uint8_t c = (a + b);
uint8_t d = c / 2;
uint8_t e = (a + b) / 2;
std::cout << unsigned(c) << ", " << unsigned(d) << ", " << unsigned(e) << "n";

4, 2, 130

这称为积分提升。操作本身在 CPU 的本机整数类型 int 中完成,该类型可以容纳大于 255 的数字。在a+b情况下,结果必须存储在uint8_t中,这就是截断的地方。在最后一种情况下,首先有一个除法作为int完成,结果可以完美地存储在uint8_t中。

a+b给出的值 260,该值未分配给任何uint8_t类型,因此在最后一种情况下您很好。仅当您将任何大于 255 的值设置为 uint8_t 时,才会出现溢出。

在以下(a + b)不溢出的情况下,编译器将ab识别为整数类型,因此加法会产生整数类型,此表达式的结果不受表达式中项或因子大小的限制。

假设变量的类型(如 ab(在这种情况下将结果限制为仅该类型。虽然有可能,但几乎不可能使用这样的语言。想象一下五个变量,当不考虑类型时,它们的总和为 500,即这个。

uint8_t a = 98;
uint8_t b = 99;
uint8_t c = 100;
uint8_t d = 101; 
uint8_t e = 102;

上述变量的总和 == 500。现在。。。在下面,任何表达式的结果都不能超过其中一个项的大小...

int incorrect = (a + b + c + d + e);

在这种情况下(a + b + c) == 41(41 + d + e)== 244。这是一个荒谬的答案..大多数人认可的替代方案即

(98 + 99 + 100 + 101 + 102) == 500;

这是类型转换存在的原因之一。

表达式中的

中间结果不应受表达式中的项或因素的限制,而应受结果类型(即左值(的限制。

@atturri是正确的。 以下是 x86 机器语言中变量发生的情况:

REP STOS DWORD PTR ES:[EDI]
MOV BYTE PTR SS:[a],0FA
MOV BYTE PTR SS:[b],0A
MOVZX EAX,BYTE PTR SS:[a] ; promotion to 32bit integer
MOVZX ECX,BYTE PTR SS:[b] ; promotion to 32bit integer
ADD EAX,ECX
MOV BYTE PTR SS:[c],AL ; ; demotion to 8bit integer
MOVZX EAX,BYTE PTR SS:[c]
CDQ
SUB EAX,EDX
SAR EAX,1
MOV BYTE PTR SS:[d],AL
MOVZX EAX,BYTE PTR SS:[a]
MOVZX ECX,BYTE PTR SS:[b]
ADD EAX,ECX
CDQ
SUB EAX,EDX
SAR EAX,1
MOV BYTE PTR SS:[e],AL