"溢出"是一个历史名词,还是物质溢出真的还在发生?

Lig*_*ica -4 c++

我相信在算术溢出期间(在为整数变量分配一个太大而无法容纳的值的上下文中),可以覆盖超出变量末尾的位.

但是在下面的C++ 11程序中,这真的仍然存在吗?我不知道它是UB,还是不允许,或者特定于实现或什么,但是当我将变量超过其最大值时,在现代架构中,我是否真的会看到内存中位的算术溢出?或者这真的更像历史事物?

int main() {
   // (not unsigned; unsigned is defined to wrap-around)
   int x = std::numeric_limits<int>::max();
   x++;
}
Run Code Online (Sandbox Code Playgroud)

Mik*_*our 7

我不知道是不是UB

它是未定义的,如C++ 11 5/4中所指定的:

如果在评估表达式期间,结果未在数学上定义或未在其类型的可表示值范围内,则行为未定义.

(正如你所说,它是为无符号类型定义的,因为它们是由3.9.1/4定义的,以遵守模运算)

在现代架构上,我实际上会看到内存中位的算术溢出吗?

在我所知的所有现代架构(x86,ARM,68000和各种DSP)中,算术是模块化的,具有固定宽度的2s补码结果; 在那些可以将结果写入内存而不是寄存器的架构上,它永远不会覆盖比结果大小更多的内存.对于加法和减法,有符号和无符号算术之间的CPU没有区别.在操作之后,可以从CPU标志的状态检测溢出(有符号或无符号).

我可以想象一个编译器,例如,一个32位DSP,试图在8或16位值上实现算术,这些值被打包成一个更大的字,其中溢出会影响字的其余部分; 但是,我见过的所有这些架构的编译器都是定义的char,short而且int是32位类型.

或者这真的更像历史事物?

它会发生在巴贝奇的差异引擎上,因为"记忆"只是一个数字; 如果你将它分成较小的数字,并且不插入保护数字,那么从一个溢出将改变下一个的值.但是,您无法在此体系结构上运行任何非平凡的C++程序.

从历史上看,我相信某些处理器会在溢出时产生异常 - 这就是行为未定义的原因.