如何判断我是否可以在C中没有溢出的情况下计算x + y?

时间:2016-02-05 02:34:27

标签: c

我只能使用这些操作! 〜& ^! +<< >>,我在抓住溢出时遇到问题,可以使用任何提示或帮助!

3 个答案:

答案 0 :(得分:0)

取决于数字是签名还是未签名。

如果两个操作数都是无符号的,则溢出将回绕到0.

如果一个或两个操作数都被签名,则行为是实现定义的,但是大多数实现表示2的补码中的有符号整数,因此在这些情况下,正溢出将回绕到负端,并且负溢出将换行好的一面。

在无符号溢出的情况下,结果将少于至少一个操作数,因此您可以这样测试:

if ((x + y < x) || (x + y < y) {
    printf("overflow\n");
}

在已签名的案例中,您首先需要检查两者是否为正(并检查否定回绕)或两者均为否定(并检查正向回绕):

if ((x > 0) && (y > 0) && ((x + y < x) || (x + y < y))) {
    printf("negative overflow\n");
}
if ((x < 0) && (y < 0) && ((x + y > x) || (x + y > y))) {
    printf("positive overflow\n");
}

正如我之前提到的,已签名的案例是实现定义的,只有当有符号整数表示为2的补码时,上述内容才有效。然而,在实践中,通常会出现这种情况。

这应该可以让您了解溢出的工作原理,尽管它并不仅仅使用您提到的特定运算符。有了这个,你应该能够弄清楚如何使用其他运算符来实现上面的表达式。

答案 1 :(得分:0)

使用有符号整数数学,除非您可以访问INT_MAX INT_MIN之类的限制,否则答案会解决未定义的行为。

#include <limits.h>

int is_overflow_add_signed(int a, int b) {
  // This uses -, so does not meet OP's goal.
  // Available as a guide
  return (a < 0) ? (b < INT_MIN - a) : (b > INT_MAX - a);
}

使用无符号数学,只需查看结果&#34; wrap&#34;周围。

int is_overflow_add_unsigned(unsigned a, unsigned b) {
  return (a + b) < a;
}

答案 2 :(得分:-1)

正如许多人所指出的那样,签署是不对的...... 所以我先把它更改为无符号。

您需要逐个计算。

由于您没有告诉我们数据类型,我认为它是4字节无符号数据。

unsigned long x, unsigned long y;
// x = ...
// y = ...
unsigned long first_byte_x = (x & 0xFF000000) >> 24;
unsigned long first_byte_y = (y & 0xFF000000) >> 24;
unsigned long other_bytes_x = x & 0x00FFFFFF;
unsigned long other_bytes_y = y & 0x00FFFFFF;
unsigned long other_bytes_sum = other_bytes_x + other_bytes_y;
unsigned long carry = (other_bytes_sum & 0xFF000000) >> 24;
unsigned long first_byte_sum = first_byte_x + first_byte_y + carry;
if (first_byte_sum > 0xFF)
    // overflow
else
    // not overflow

如果你可以使用mod(%),那么它会更简单。

*看起来像是一个家庭作业,所以我希望你在考虑之前就考虑过了......