c - C 编译器是否假设有符号整数的加法是可交换的?

标签 c integer-overflow

我正在尝试检查带符号的加法是否会溢出。通常,检查是否

int a + int b

会溢出(a 和 b 都是正数),我检查是否

if (a > INT_MAX - b)

但是现在我想检查一下

int a + int b - int c

会溢出。我知道 a、b 和 c 是正数并且 b >= c,所以我进行以下检查:

if (a > INT_MAX - b + c)

现在我的问题是,编译器可以重写

INT_MAX - b + c     to     INT_MAX + c - b   ?

我担心的是,它会首先执行 INT_MAX + c,这可能会溢出并导致未定义的行为。

最佳答案

在推理未定义的行为时考虑“编译器”做什么是一种谬论。编译器是透明的。该行为在您的代码中,而不是在编译器中。你应该问“我的代码 INT_MAX - b + c 是什么意思?它会溢出吗?答案永远不在“编译器”中,但在标准中。

标准只要求出现在您的程序中的个别操作不会溢出。它从不提及任何未明确出现在您的程序中的重写表达式。 INT_MAX - b + c 在你的程序中,等同于 (INT_MAX - b) + c。所以要求是(INT_MAX - b)不溢出,然后加到c上的结果不溢出。 INT_MAX + c - b 不会出现在您的程序中,因此您不必担心。

如果编译器以任何方式重写您的表达式,它必须根据as-if 规则确保重写的表达式与您的表达式具有相同的可见行为。因此,如果它确实将 INT_MAX - b + c 替换为 INT_MAX + c - b,它必须确保溢出不会发生或被透明地处理(例如被忽略由硬件)。

关于c - C 编译器是否假设有符号整数的加法是可交换的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52243398/

相关文章:

c++ - 如何在 C++ 中处理大至 2^9000000 的整数

java - 为什么这个Java长溢出来了?

代码设计——状态机或程序代码

c - 稀疏矩阵函数

c++ - 引用计数智能指针如何避免或处理引用计数器溢出?

c++ - 散列溢出

c++ - Ruby 模仿 C 整数数据类型和 union

c - 具有指定初始化程序的 MSVC12 (VS2013) 中可能存在编译器错误

更改返回地址以指向 shellcode

c++ - (-2147483648> 0) 在 C++ 中返回 true?