c - C 编译器是否假设有符号整数的加法是可交换的?
问题描述
我正在尝试检查签名添加是否会溢出。一般来说,检查是否
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
,它必须确保溢出不会发生或被透明地处理(例如被硬件忽略)。
推荐阅读
- encryption - 显示不同结果的密钥?
- python - 为MultiIndex DataFrame的交叉选择分配值(numpy的省略号样式)
- git - 如何处理由目标分支中移动的文件引起的合并冲突
- python - Python:使用 map 和 reduce 编写外积
- html - 为什么双引号 urlencoded 为 %22?
- python - 等待 bash 提示出现的 Python 脚本
- asp.net - 使用 vbscript ASP 获取 XML 中的值节点
- java - 使用 Fat Jars 优于 Container 的优势
- sharepoint - Sharepoint 2010 设计器文档审批工作流程
- javascript - 尝试在 guillotine.js 中显示具有动态宽度和高度的图像。在固定宽度和高度下工作正常