我正在尝试检查带符号的加法是否会溢出。通常,检查是否
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/