如何检测 C [重复] 中的整数溢出

共3个回答,已解决, 标签: c overflow

这个问题在这里已经有了答案:

我们知道, 当数字变大时, Cpithon 会将整数自动提升到长整数 (允许任意精度的算术)。

我们如何检测纯 int c 的溢出和 long long 在纯 c 中溢出?

第1个答案(采用)

你可以预测 signed int overflow , 但试图在求和为时已晚后检测它。在执行签名添加之前, 必须测试可能的溢出。

不可能通过在求和后对其进行测试来避免未定义的行为。如果加法溢出, 那么就已经有了未定义的行为。

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



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;="" }="">

有关详细信息, 请参阅本文。您还可以在同一篇论文中找到为什么无符号整数溢出不是未定义的行为, 以及可能存在的可移植性问题。

编辑:

GCC 和其他编译器有一些规定来检测溢出。例如, GCC 下面的内置函数允许执行简单的算术运算, 同时检查操作是否溢出。

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 溢出未定义, 而未签名的指定不是。

答案取决于编译器的实现。大多数 C 实现 (编译器) 只是使用了它所使用的整数表示最容易实现的任何溢出行为。

实际上, 已签名值的表示形式可能不同 (根据实现): one's complement two's complement , sign-magnitude 。对于无符号类型, 该标准没有理由允许变体, 因为只有一个明显 binary representation 的 (标准只允许二进制表示)。

第2个答案

您无法检测到签名 int 溢出。您必须编写代码才能避免它。

签名 int 溢出是未定义的行为, 如果它存在于您的程序中, 则该程序无效, 并且不需要编译器生成任何特定行为。

第3个答案

在执行添加之前, 必须测试签名的操作数。这里是一个安全的加法函数与 2 个比较在所有情况下:



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

如果已知该类型 long long 的范围大于类型 int , 则可以使用此方法, 这可能会更快:



int safe_add(int a, int b) {
    long long res = (long long)a + b;
    if (res > INT_MAX || res < int_min)="" {="" handle="" overflow="" */="" }="" else="" {="" return="" (int)res;="" }="" }="">

相关问题

我投的是 malloc 的结果吗? 为什么是统计:: st _ size 0 为设备, 但同时 lseek 正确地定义了设备大小? 允许在易失对象上进行优化 如何检测 C [重复] 中的整数溢出 最新版本的谷歌 Chrome, 73.0, 网页应用程序的溢出不再起作用