如何在C中减去两个带符号的32位数时检测溢出?

Mur*_*rph 1 c integer-overflow

我有两个有符号的整数,我想减去它们.我需要知道它是否溢出.

int one;
int two;
int result = two-one;

if (OVERFLOW) {
    printf("overflow");
} else {
    printf("no overflow");
}
Run Code Online (Sandbox Code Playgroud)

这样的事情.有没有办法做到这一点?

pmg*_*pmg 10

你需要它发生之前捕获过低(或下溢).一旦它发生,你就处于Undefined Behavior土地上并且所有赌注都已关闭.

#include <limits.h>
#include <stdio.h>

int sum_invokes_UB(int a, int b) {
  int ub = 0;
  if ((b < 0) && (a < INT_MIN - b)) ub = 1;
  if ((b > 0) && (a > INT_MAX - b)) ub = 1;
  return ub;
}

int main(void) {
  printf("(INT_MAX-10) + 8: %d\n", sum_invokes_UB(INT_MAX - 10, 8));
  printf("(INT_MAX-10) + 100: %d\n", sum_invokes_UB(INT_MAX - 10, 100));
  printf("(INT_MAX-10) + INT_MIN: %d\n", sum_invokes_UB(INT_MAX - 10, INT_MIN));
  printf("100 + INT_MIN: %d\n", sum_invokes_UB(100, INT_MIN));
  printf("-100 + INT_MIN: %d\n", sum_invokes_UB(-100, INT_MIN));
  printf("INT_MIN - 100: %d\n", sum_invokes_UB(INT_MIN, -100));
  return 0;
}
Run Code Online (Sandbox Code Playgroud)


AnT*_*AnT 6

首先,签名计算中的溢出会导致C中的未定义行为.

其次,忘记UB一秒钟并坚持2的补码机器的典型溢出行为:溢出是由于结果从第一个操作数"向错误的方向""移动",即当结果结束时更大比具有正的第二操作数的第一个操作数(或小于具有第二个操作数的第一个操作数).

在你的情况下

int one, two;

int result = two - one;
if ((result < two) != (one > 0))
  printf("overflow");
Run Code Online (Sandbox Code Playgroud)

  • 如果 `int result = 二 - 一;` 溢出(或下溢),那么您就处于未定义行为状态,任何事情都可能发生。 (2认同)