有符号整数溢出在C++中仍然是未定义的行为吗?

nwsw7zdq  于 2023-02-20  发布在  其他
关注(0)|答案(3)|浏览(135)

正如我们所知,signed integer overflow is undefined behavior.但是在C++11 cstdint文档中有一些有趣的东西:
有符号整数类型,宽度分别为8、16、32和64位,没有填充位,对负值使用2的补码(仅在实现直接支持该类型时提供)
See link
我的问题是:既然标准明确规定int8_tint16_tint32_tint64_t的负数是2的补码,那么这些类型的溢出是否仍然是未定义的行为?

    • 编辑**我检查了C++11和C11标准,以下是我的发现:

C++11语言第18.4.1节:
标头定义了所有函数、类型和宏,与C标准中的7.20相同。
第C11节,第7.20.1.1节:
typedef名称intN_t表示宽度为N、没有填充位、并且是二进制补码表示的有符号整数类型,因此,int8_t表示宽度正好为8位的有符号整数类型。

8zzbczxx

8zzbczxx1#

这些类型溢出仍然是未定义的行为吗?

**是。**根据C++11标准的第5/4段(关于一般的表达式):

如果在表达式的求值过程中,结果没有数学定义或不在其类型的可表示值范围内,行为是未定义的。[...]
事实上,二进制补码表示用于那些有符号类型并不意味着在计算那些类型的表达式时使用算术模2^n。
另一方面,关于 unsigned 算术,本标准明确规定(第3.9.1/4段):
声明为unsigned的无符号整数应遵循模2^n的算术法则,其中n是该特定大小整数的值表示中的位数
这意味着无符号算术运算的结果总是“* 数学定义的 *",并且结果总是在可表示的范围内;因此,5/4不适用,脚注46对此作了解释:
46)这意味着unsigned算术不会溢出,因为不能由所得的无符号整数类型表示的结果是以比可由所得的无符号整数类型表示的最大值大1的数为模而缩减的。

btqmn9zl

btqmn9zl2#

仅仅因为一个类型被定义为使用2的补码表示,并不意味着该类型中的算术溢出被定义。
有符号算术溢出的未定义行为用于实现优化;例如,编译器可以假设如果a > b,则a + 1 > b也;这在无符号算术中不成立,在无符号算术中,由于a + 1可能绕回0,因此需要执行第二次检查。此外,一些平台可以在算术溢出时生成陷阱信号(例如,参见http://www.gnu.org/software/libc/manual/html_node/Program-Error-Signals.html);该标准继续允许这种情况发生。

b09cbbtk

b09cbbtk3#

我想是的。
来自标准文档(第4页和第5页):

1.3.24未定义的行为

本国际标准未作要求的行为
[注:当本国际标准省略任何明确的行为定义或当程序使用错误的结构或错误的数据时,可能会出现未定义的行为。允许的未定义行为包括完全忽略具有不可预测结果的情况,以及在翻译或程序执行期间以文件化的方式表现的环境特征(发出或不发出诊断信息)到终止翻译或执行(发出诊断信息)。许多错误的程序结构不会产生未定义的行为;需要进行诊断。--尾注]

相关问题