算术溢出会覆盖数据吗?
Does arithmetic overflow overwrite data?
std::uint8_t x = 256; //Implicitly converts to 0
std::uint8_t y = 255;
y++;
对于 x,我假设一切都已处理,因为使用从 int
到 uint8_t
的某些定义的转换,100000000
被转换为 00000000
。 x
的内存应该是0 00000000
而不是1 00000000
.
但是 y
我相信溢出会留在内存中。 y
最初是 11111111
。加1后变成1 00000000
。这回绕回 0
因为 y
只查看 8 LSB。
y++;
之后的1
是留在内存中,还是加完就丢弃?
如果存在,它会在 y
之前损坏数据吗?
Does arithmetic overflow overwrite data?
有符号算术溢出的行为未定义。不保证覆盖数据,也不保证不覆盖数据
std::uint8_t y = 255;
y++;
无符号溢出定义明确。 y
会是0,没有其他的side-effects.
引自 C++ 标准(最新草案):
[basic.fundamental]
... The range of representable values for the unsigned type is 0 to 2N−1 (inclusive); arithmetic for the
unsigned type is performed modulo 2N.
[Note 2: Unsigned arithmetic does not overflow.
Overflow for signed arithmetic yields undefined behavior ([expr.pre]).
— end note]
[expr.pre]
If during the evaluation of an expression, the result is not mathematically defined or not in the range of representable values for its type, the behavior is undefined.
由于无符号算术是模块化的,因此结果永远不会超出可表示值范围。
在启用优化的情况下使用 gcc 时,除非使用 -fwrapv 编译器选项,否则整数溢出可能会任意破坏程序行为,导致内存损坏,即使溢出的计算结果不会被使用。阅读已发布的基本原理,标准的作者似乎不太可能期望普通平台的 general-purpose 编译器以这种方式运行,但标准并没有试图预测和禁止所有无端无意义的方式实现可能会处理事情。
std::uint8_t x = 256; //Implicitly converts to 0
std::uint8_t y = 255;
y++;
对于 x,我假设一切都已处理,因为使用从 int
到 uint8_t
的某些定义的转换,100000000
被转换为 00000000
。 x
的内存应该是0 00000000
而不是1 00000000
.
但是 y
我相信溢出会留在内存中。 y
最初是 11111111
。加1后变成1 00000000
。这回绕回 0
因为 y
只查看 8 LSB。
y++;
之后的1
是留在内存中,还是加完就丢弃?
如果存在,它会在 y
之前损坏数据吗?
Does arithmetic overflow overwrite data?
有符号算术溢出的行为未定义。不保证覆盖数据,也不保证不覆盖数据
std::uint8_t y = 255; y++;
无符号溢出定义明确。 y
会是0,没有其他的side-effects.
引自 C++ 标准(最新草案):
[basic.fundamental]
... The range of representable values for the unsigned type is 0 to 2N−1 (inclusive); arithmetic for the unsigned type is performed modulo 2N.
[Note 2: Unsigned arithmetic does not overflow. Overflow for signed arithmetic yields undefined behavior ([expr.pre]). — end note]
[expr.pre]
If during the evaluation of an expression, the result is not mathematically defined or not in the range of representable values for its type, the behavior is undefined.
由于无符号算术是模块化的,因此结果永远不会超出可表示值范围。
在启用优化的情况下使用 gcc 时,除非使用 -fwrapv 编译器选项,否则整数溢出可能会任意破坏程序行为,导致内存损坏,即使溢出的计算结果不会被使用。阅读已发布的基本原理,标准的作者似乎不太可能期望普通平台的 general-purpose 编译器以这种方式运行,但标准并没有试图预测和禁止所有无端无意义的方式实现可能会处理事情。