为什么C和C++没有内置方法来检查整数溢出?

Fir*_*cer 21 c c++ integer-overflow

为什么C和C++没有提供一组实现提供的操作来执行提供溢出检查的每个基本整数操作(例如a bool safeAdd(int *out, int a, int b)).

据我所知,大多数指令集都有办法判断操作是否溢出(例如x86溢出和进位标志),并且在有符号整数的情况下也会发生定义.

因此,编译器是否应该能够做得更好,创建更简单,更快速的操作,而不是用C和C++编写代码?

Dou*_* T. 10

C和C++遵循"你不为你不需要付出代价"的中心原则.因此,默认算术运算不会偏离底层架构的算术运算单指令.

至于为什么没有标准库函数来添加两个整数和检测溢出,我不能说.首先,看起来语言将有符号整数溢出定义为未定义的行为:

在C编程语言中,带符号的整数溢出会导致未定义的行为,

考虑到有多种方法可以实现有符号整数(一个补码,两个补码等),并且在创建C时,这些架构都很普遍,可以理解为什么这个架构是未定义的.如果没有关于底层平台的大量信息,很难实现"安全*" 纯C函数.它可以在逐个CPU的基础上完成.

仍然这不会使它变得不可能.如果有人能够通过更安全的溢出助手找到C或C++标准组织的提案并且能够看到他们被拒绝的原因,我肯定会感兴趣.

无论如何,在实践中有很多方法可以检测算术溢出和库以提供帮助.


Jam*_*nze 6

可能是因为没有需求.算术溢出是未定义的行为,表示允许实现进行此类检查.如果编译器供应商认为这样做会销售更多的编译器,他们就会.

实际上,编译器非常非常难以比程序员更有效地完成它们.验证所有数字输入的范围是一个非常标准的过程,可以证明以后的操作不会溢出.所有优秀的程序员都习惯这样做.所以这意味着if 在输入后立即快速,并且不再进一步检查.

尽管如此,程序员已经知道会犯错误,但是在以后更改计算时忘记更正验证很简单.我想在编译器中看到这样的功能.但显然,它不会有助于销售编译器,或者至少供应商认为它不会,所以我们没有得到它.

  • @DougT. - 一般情况下都不是这样,部分是因为不清楚是否有"更安全"的东西.原子确实保证有符号值的上溢和下溢换行,就好像表示是2s补码一样. (2认同)

Mat*_* M. 6

这个问题经常出现.

首先,请记住,C被定义为便携高效.因此,它被设计为仅提供由许多硬件支持的操作(可能在x86之前甚至看到了光的一天).

其次,许多编译器为这样的操作提供(或计划提供)内置函数,以便用户可以使用在引擎盖下使用这些内置函数的类类型.内置函数的实现质量并不是那么重要(尽管它是这样),因为编译器意识到它们的含义可能会在它们可证明无用时优化检出.

最后,还有其他方法来实际检查程序.例如,静态分析或特殊编译模式和单元测试可以及早发现这些缺陷,并避免(或多或少完全)在Release版本中嵌入这些溢出检查的需要.


Chr*_*ica 5

因为它很少需要.你什么时候需要检测整数溢出?在几乎所有情况下,当您需要检查某个范围时,通常需要定义实际范围,因为此范围完全取决于应用程序和算法.

你何时真的需要知道结果是否溢出了范围int而不是知道结果是否在特定算法的允许域内,或者索引是否在数组的边界内?是您为变量提供语义,语言规范仅为您提供类型的整体范围,如果您选择的范围不符合您的需求,那么这就是您的错.

整数溢出是UB,因为你很少真正关心它.如果我unsigned char在操作期间溢出,我可能选择了错误的类型来累积1000万个数字.但是在运行期间了解溢出对我没有帮助,因为无论如何我的设计都被打破了.