乍一看,这个问题看起来像是如何检测整数溢出的重复?然而,它实际上是显着不同的.
我发现虽然检测无符号整数溢出非常简单,但在C/C++中检测带符号的溢出实际上比大多数人想象的要困难.
最明显但又天真的方式是这样的:
int add(int lhs, int rhs)
{
 int sum = lhs + rhs;
 if ((lhs >= 0 && sum < rhs) || (lhs < 0 && sum > rhs)) {
  /* an overflow has occurred */
  abort();
 }
 return sum; 
}
这个问题是根据C标准,有符号整数溢出是未定义的行为. 换句话说,根据标准,只要您甚至导致签名溢出,您的程序就像取消引用空指针一样无效.因此,您不能导致未定义的行为,然后尝试在事后检测溢出,如上面的后置条件检查示例.
尽管上面的检查很可能适用于许多编译器,但你不能指望它.实际上,因为C标准说未定义有符号整数溢出,所以一些编译器(如GCC)将在设置优化标志时优化上述检查,因为编译器假定有符号溢出是不可能的.这完全打破了检查溢出的尝试.
因此,检查溢出的另一种可能方法是:
int add(int lhs, int rhs)
{
 if (lhs >= 0 && rhs >= 0) {
  if (INT_MAX - lhs <= rhs) {
   /* overflow …众所周知,有符号整数溢出是未定义的行为.但是C++ 11 cstdint文档中有一些有趣的东西:
有符号整数类型,宽度分别为8,16,32和64位,没有填充位,负值使用2的补码(仅当实现直接支持该类型时提供)
这里是我的问题:由于标准明确地说,对int8_t,int16_t,int32_t和int64_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位.
在C++中表示128位数的最佳方法是什么?它应该尽可能地与内置数值类型一致(即支持所有算术运算符等).
我正在考虑构建一个具有2个64位或4个32位数的类.或者可能只是创建一个128位的内存块并自己完成所有操作.
是否有一些更容易/更标准的方式,或者我自己实施它时不太可能搞砸的东西?:)
如果它可以扩展到256位,512位等等也会很好...
有(1):
// assume x,y are non-negative
if(x > max - y) error;
并且(2):
// assume x,y are non-negative
int sum = x + y;
if(sum < x || sum < y) error;
哪个是首选或有更好的方法.
我知道这样的话题被问过好几次,但我的问题是关于整个32位int的溢出.例如:
  11111111111111111111111111111111 +
  00000000000000000000000000000001 =
  00000000000000000000000000000000   //overflow!
我找到了类似问题的主题,但算法并不完美.
  11111111111111111111111111111111 +
  00000000000000000000000000000000 =
  00000000000000000000000000000000  //overflow!
有没有简单快捷的方法来检查这个?
java integer bit-manipulation integer-overflow integer-arithmetic
假设我们有2个常数A&B和一个变量i,所有64位整数.我们想要计算一个简单的通用算术运算,例如:
i * A / B    (1)
为了简化问题,我们假设变量i总是在范围内[INT64_MIN*B/A, INT64_MAX*B/A],因此算术运算(1)的最终结果不会溢出(即:适合该范围[INT64_MIN, INT64_MAX]).
另外,i假设更有可能在友好范围Range1 = [INT64_MIN/A, INT64_MAX/A](即:接近0),但是i可能(不太可能)在该范围之外.在第一种情况下,一个平凡的整数计算i * A不会溢出(这就是我们称之为范围友好的原因); 并且在后一种情况下,i * A将会溢出的平凡整数计算,导致(1)的计算中的错误结果.
什么是"最安全"和"最有效"的计算操作方法(1)(其中"最安全"意味着:保持准确性或至少相当精确,"最有效"意味着:最低平均计算时间),提供i更有可能在友谊范围Range1.
目前,代码中当前实现的解决方案如下:
(int64_t)((double)A / B * i)
哪个解决方案非常安全(没有溢出)虽然不准确(由于双重有效位和53位限制导致的精度损失)并且非常快,因为(double)A / B在编译时预分配了双重除法,只允许在运行时计算双乘法.
我有2个号码:A和B.我需要A+B在代码中的某处计算.这两个A和B的long long,并可以积极或消极的.
我的代码运行错误,我怀疑计算时会出现问题A+B.我只想检查是否A+B超出long long范围.因此,任何方法都是可以接受的,因为我只将它用于调试.
为什么C和C++没有提供一组实现提供的操作来执行提供溢出检查的每个基本整数操作(例如a bool safeAdd(int *out, int a, int b)).
据我所知,大多数指令集都有办法判断操作是否溢出(例如x86溢出和进位标志),并且在有符号整数的情况下也会发生定义.
因此,编译器是否应该能够做得更好,创建更简单,更快速的操作,而不是用C和C++编写代码?
我想将两个数相乘,并检测是否有溢出.最简单的方法是什么?
我们知道CPython在数字变大时会无声地将整数提升为长整数(允许任意精度算术)。
我们如何检测的溢出int和long long纯C?