如何在C中检测整数溢出 [英] How to detect integer overflow in C

查看:342
本文介绍了如何在C中检测整数溢出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们知道CPython在数字变大时会无声地将整数提升为长整数(允许任意精度算术).

We know CPython promotes integers to long integers (which allow arbitrary-precision arithmetic) silently when the number gets bigger.

我们如何检测纯C中intlong long的溢出?

How can we detect overflow of int and long long in pure C?

推荐答案

您可以预测signed int overflow,但尝试在求和后才检测到它.在进行签名添加之前,您必须测试可能的溢出.

You can predict signed int overflow but attempting to detect it after the summation is too late. You have to test for possible overflow before you do a signed addition.

通过在求和后进行测试来避免未定义的行为是不可能的.如果添加溢出,则已经存在未定义的行为.

It's not possible to avoid undefined behaviour by testing for it after the summation. If the addition overflows then there is already undefined behaviour.

如果是我,我会做这样的事情:

If it were me, I'd do something like this:

#include <limits.h>

int safe_add(int a, int b) 
{
    if (a >= 0) {
        if (b > (INT_MAX - a)) {
            /* handle overflow */
        }
    } else {
        if (b < (INT_MIN - a)) {
            /* handle underflow */
        }
    }
    return a + b;
}

有关更多信息,请参见纸张.您还可以在同一篇文章中找到为什么无符号整数溢出不是未定义的行为以及可能是可移植性的问题.

Refer this paper for more information. You can also find why unsigned integer overflow is not undefined behaviour and what could be portability issues in the same paper.

GCC和其他编译器有一些规定来检测溢出.例如,GCC具有以下内置函数,可以执行简单的算术运算并检查运算是否溢出.

GCC and other compilers have some provisions to detect the overflow. For example, GCC has following built-in functions allow performing simple arithmetic operations together with checking whether the operations overflowed.

bool __builtin_add_overflow (type1 a, type2 b, type3 *res)
bool __builtin_sadd_overflow (int a, int b, int *res)
bool __builtin_saddl_overflow (long int a, long int b, long int *res)
bool __builtin_saddll_overflow (long long int a, long long int b, long long int *res)
bool __builtin_uadd_overflow (unsigned int a, unsigned int b, unsigned int *res)
bool __builtin_uaddl_overflow (unsigned long int a, unsigned long int b, unsigned long int *res)
bool __builtin_uaddll_overflow (unsigned long long int a, unsigned long long int b, unsigned long long int *res)

访问此链接.

关于某人提出的问题

我认为,解释为什么有符号的int溢出未定义,而无符号的正确地溢出不是很好.

I think, it would be nice and informative to explain why signed int overflow undefined, whereas unsigned apperantly isn't..

答案取决于编译器的实现.大多数C实现(编译器)使用的最简单的溢出行为就是使用它使用的整数表示形式.

The answer depends upon the implementation of the compiler. Most C implementations (compilers) just used whatever overflow behaviour was easiest to implement with the integer representation it used.

实际上,有符号值的表示形式可能有所不同(根据实现方式):one's complementtwo's complementsign-magnitude.对于无符号类型,标准没有理由允许变化,因为只有一个明显的binary representation(标准仅允许二进制表示).

In practice, the representations for signed values may differ (according to the implementation): one's complement, two's complement, sign-magnitude. For an unsigned type there is no reason for the standard to allow variation because there is only one obvious binary representation (the standard only allows binary representation).

这篇关于如何在C中检测整数溢出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆