2

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

4

4 回答 4

2

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

于 2016-04-11T05:49:11.937 回答
0

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

于 2016-04-11T05:48:23.017 回答
0

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

让我们假设变量的类型,a或者b在这种情况下将结果限制为仅该类型。虽然可能,但几乎不可能使用这样的语言。想象五个变量,当不考虑类型时,它们的总和为 500,即 this..

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;

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

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

于 2016-04-11T07:54:15.937 回答
0

@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
于 2016-04-11T07:58:36.303 回答