问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

C语言中怎么处理溢出

发布网友 发布时间:2022-04-29 18:13

我来回答

5个回答

热心网友 时间:2023-10-29 17:18

 
 
 
C 中调用积运算符之后做溢出检测已经太晚,但调用和运算符之后做检测则一点也不迟,
所以你可以通过对和运算结果的检测实现能检测溢出的积运算,因为 a * b 既是 a 个 b 的和:

-5000000 * 1374389539 等于 -(5000000 * 1374389539)。括号里是 5000000 个 1374389539 的和。

我把能检测溢出的和运算包在 add( ) 里,然后在 multiply( ) 里重复调用 add( )。

add( ) 怎么检测溢出?

和运算的结果若溢出将导致数值的环绕。上溢导致往下环绕,下溢导致往上环绕。

边界状况:

(1)最轻微的上溢是 INT_MAX + 1 :结果是 INT_MIN。
(2)最严重的上溢是 INT_MAX + INT_MAX :结果是 -2。

(3)最轻微的下溢是 INT_MIN - 1 :结果是 INT_MAX。
(4)最严重的下溢是 INT_MIN - INT_MIN :结果是 0。

结论:

(1)所有上溢结果都小于任何一个操作数。
(2)所有下溢结果都大于任何一个操作数。

所以 add( ) 可以用结果和任意选定的一个参数判断溢出,并以落选的参数判断溢出的方向。

add( ) 无法以返回值举报溢出,所以采用 strtol( ) 的举报方法。

不同于 strtol( ) 的是,若没有溢出,add( ) 会把 0 赋值给 errno。
multiply( ) 在这方面跟 add( ) 一样。
 
 
 
#include<stdio.h>
#include<errno.h> /* errno, ERANGE */
 
 
/*
 * Returns the sum of a and b, with overflow and underflow check.
 * If overflow or underflow occurred, sets errno to ERANGE, else to 0.
 */
int add( int a, int b ) {

    int result = a + b;

    if( b > 0 && result > a || b <= 0 && result <= a )
        errno = 0;
    else
        errno = ERANGE;

    return result;
}
 
 
/*
 * Returns the proct of a and b obtained through repeated call of add( ).
 * Affects errno exactly as add( ) does.
 */
int multiply( int a, int b ) {

    int sign_of_a = 1,
        result = 0,
             i = 0;

    /* Keep the sign of multiplier off the loop sentinel. */
    if( a < 0 ) {
        sign_of_a = -1;
        a *= -1;
    }

    /* Have to reset errno here because it won't be updated if a is 0. */
    errno = 0;

    while( i++ < a ) {
        result = add( result, b );
        if( errno == ERANGE )
            break;
    }

    return result * sign_of_a;
}
 
 
 
int main( ) {

    int result;

    /* Operands too huge: sure overflow. */
    result = multiply( -5000000, 1374389539 );
    if( errno == ERANGE )
        perror( "Uh oh" );
    else
        printf( "%d\n", result );

    /* Small operands: safe. */
    result = multiply( 49, -972 );
    if( errno == ERANGE )
        perror( "Uh oh" );
    else
        printf( "%d\n", result );

}
 
 
 
当然,应付溢出的最佳方法还是防范:充分了解数据的范围,选择恰当的变量类型。

也许你正考虑改用不需要你担心整数类型溢出的语言。考虑过 Python 吗?
 
 
 

热心网友 时间:2023-10-29 17:18

把int型换成long型
一般来说long型占64位

热心网友 时间:2023-10-29 17:18

 
 
 
C 中调用积运算符之后做溢出检测已经太晚,但调用和运算符之后做检测则一点也不迟,
所以你可以通过对和运算结果的检测实现能检测溢出的积运算,因为 a * b 既是 a 个 b 的和:

-5000000 * 1374389539 等于 -(5000000 * 1374389539)。括号里是 5000000 个 1374389539 的和。

我把能检测溢出的和运算包在 add( ) 里,然后在 multiply( ) 里重复调用 add( )。

add( ) 怎么检测溢出?

和运算的结果若溢出将导致数值的环绕。上溢导致往下环绕,下溢导致往上环绕。

边界状况:

(1)最轻微的上溢是 INT_MAX + 1 :结果是 INT_MIN。
(2)最严重的上溢是 INT_MAX + INT_MAX :结果是 -2。

(3)最轻微的下溢是 INT_MIN - 1 :结果是 INT_MAX。
(4)最严重的下溢是 INT_MIN - INT_MIN :结果是 0。

结论:

(1)所有上溢结果都小于任何一个操作数。
(2)所有下溢结果都大于任何一个操作数。

所以 add( ) 可以用结果和任意选定的一个参数判断溢出,并以落选的参数判断溢出的方向。

add( ) 无法以返回值举报溢出,所以采用 strtol( ) 的举报方法。

不同于 strtol( ) 的是,若没有溢出,add( ) 会把 0 赋值给 errno。
multiply( ) 在这方面跟 add( ) 一样。
 
 
 
#include<stdio.h>
#include<errno.h> /* errno, ERANGE */
 
 
/*
 * Returns the sum of a and b, with overflow and underflow check.
 * If overflow or underflow occurred, sets errno to ERANGE, else to 0.
 */
int add( int a, int b ) {

    int result = a + b;

    if( b > 0 && result > a || b <= 0 && result <= a )
        errno = 0;
    else
        errno = ERANGE;

    return result;
}
 
 
/*
 * Returns the proct of a and b obtained through repeated call of add( ).
 * Affects errno exactly as add( ) does.
 */
int multiply( int a, int b ) {

    int sign_of_a = 1,
        result = 0,
             i = 0;

    /* Keep the sign of multiplier off the loop sentinel. */
    if( a < 0 ) {
        sign_of_a = -1;
        a *= -1;
    }

    /* Have to reset errno here because it won't be updated if a is 0. */
    errno = 0;

    while( i++ < a ) {
        result = add( result, b );
        if( errno == ERANGE )
            break;
    }

    return result * sign_of_a;
}
 
 
 
int main( ) {

    int result;

    /* Operands too huge: sure overflow. */
    result = multiply( -5000000, 1374389539 );
    if( errno == ERANGE )
        perror( "Uh oh" );
    else
        printf( "%d\n", result );

    /* Small operands: safe. */
    result = multiply( 49, -972 );
    if( errno == ERANGE )
        perror( "Uh oh" );
    else
        printf( "%d\n", result );

}
 
 
 
当然,应付溢出的最佳方法还是防范:充分了解数据的范围,选择恰当的变量类型。

也许你正考虑改用不需要你担心整数类型溢出的语言。考虑过 Python 吗?
 
 
 

热心网友 时间:2023-10-29 17:18

 
 
 
C 中调用积运算符之后做溢出检测已经太晚,但调用和运算符之后做检测则一点也不迟,
所以你可以通过对和运算结果的检测实现能检测溢出的积运算,因为 a * b 既是 a 个 b 的和:

-5000000 * 1374389539 等于 -(5000000 * 1374389539)。括号里是 5000000 个 1374389539 的和。

我把能检测溢出的和运算包在 add( ) 里,然后在 multiply( ) 里重复调用 add( )。

add( ) 怎么检测溢出?

和运算的结果若溢出将导致数值的环绕。上溢导致往下环绕,下溢导致往上环绕。

边界状况:

(1)最轻微的上溢是 INT_MAX + 1 :结果是 INT_MIN。
(2)最严重的上溢是 INT_MAX + INT_MAX :结果是 -2。

(3)最轻微的下溢是 INT_MIN - 1 :结果是 INT_MAX。
(4)最严重的下溢是 INT_MIN - INT_MIN :结果是 0。

结论:

(1)所有上溢结果都小于任何一个操作数。
(2)所有下溢结果都大于任何一个操作数。

所以 add( ) 可以用结果和任意选定的一个参数判断溢出,并以落选的参数判断溢出的方向。

add( ) 无法以返回值举报溢出,所以采用 strtol( ) 的举报方法。

不同于 strtol( ) 的是,若没有溢出,add( ) 会把 0 赋值给 errno。
multiply( ) 在这方面跟 add( ) 一样。
 
 
 
#include<stdio.h>
#include<errno.h> /* errno, ERANGE */
 
 
/*
 * Returns the sum of a and b, with overflow and underflow check.
 * If overflow or underflow occurred, sets errno to ERANGE, else to 0.
 */
int add( int a, int b ) {

    int result = a + b;

    if( b > 0 && result > a || b <= 0 && result <= a )
        errno = 0;
    else
        errno = ERANGE;

    return result;
}
 
 
/*
 * Returns the proct of a and b obtained through repeated call of add( ).
 * Affects errno exactly as add( ) does.
 */
int multiply( int a, int b ) {

    int sign_of_a = 1,
        result = 0,
             i = 0;

    /* Keep the sign of multiplier off the loop sentinel. */
    if( a < 0 ) {
        sign_of_a = -1;
        a *= -1;
    }

    /* Have to reset errno here because it won't be updated if a is 0. */
    errno = 0;

    while( i++ < a ) {
        result = add( result, b );
        if( errno == ERANGE )
            break;
    }

    return result * sign_of_a;
}
 
 
 
int main( ) {

    int result;

    /* Operands too huge: sure overflow. */
    result = multiply( -5000000, 1374389539 );
    if( errno == ERANGE )
        perror( "Uh oh" );
    else
        printf( "%d\n", result );

    /* Small operands: safe. */
    result = multiply( 49, -972 );
    if( errno == ERANGE )
        perror( "Uh oh" );
    else
        printf( "%d\n", result );

}
 
 
 
当然,应付溢出的最佳方法还是防范:充分了解数据的范围,选择恰当的变量类型。

也许你正考虑改用不需要你担心整数类型溢出的语言。考虑过 Python 吗?
 
 
 

热心网友 时间:2023-10-29 17:18

把int型换成long型
一般来说long型占64位

热心网友 时间:2023-10-29 17:19

在现在的Windows平台下,长整型是long long或者__int64,是64位,而long应该是32位的,不是64的。

热心网友 时间:2023-10-29 17:19

长整型已经足够满足日常的使用了

热心网友 时间:2023-10-29 17:20

换长整型

热心网友 时间:2023-10-29 17:19

在现在的Windows平台下,长整型是long long或者__int64,是64位,而long应该是32位的,不是64的。

热心网友 时间:2023-10-29 17:19

长整型已经足够满足日常的使用了

热心网友 时间:2023-10-29 17:20

换长整型

热心网友 时间:2023-10-29 17:18

把int型换成long型
一般来说long型占64位

热心网友 时间:2023-10-29 17:19

在现在的Windows平台下,长整型是long long或者__int64,是64位,而long应该是32位的,不是64的。

热心网友 时间:2023-10-29 17:19

长整型已经足够满足日常的使用了

热心网友 时间:2023-10-29 17:18

 
 
 
C 中调用积运算符之后做溢出检测已经太晚,但调用和运算符之后做检测则一点也不迟,
所以你可以通过对和运算结果的检测实现能检测溢出的积运算,因为 a * b 既是 a 个 b 的和:

-5000000 * 1374389539 等于 -(5000000 * 1374389539)。括号里是 5000000 个 1374389539 的和。

我把能检测溢出的和运算包在 add( ) 里,然后在 multiply( ) 里重复调用 add( )。

add( ) 怎么检测溢出?

和运算的结果若溢出将导致数值的环绕。上溢导致往下环绕,下溢导致往上环绕。

边界状况:

(1)最轻微的上溢是 INT_MAX + 1 :结果是 INT_MIN。
(2)最严重的上溢是 INT_MAX + INT_MAX :结果是 -2。

(3)最轻微的下溢是 INT_MIN - 1 :结果是 INT_MAX。
(4)最严重的下溢是 INT_MIN - INT_MIN :结果是 0。

结论:

(1)所有上溢结果都小于任何一个操作数。
(2)所有下溢结果都大于任何一个操作数。

所以 add( ) 可以用结果和任意选定的一个参数判断溢出,并以落选的参数判断溢出的方向。

add( ) 无法以返回值举报溢出,所以采用 strtol( ) 的举报方法。

不同于 strtol( ) 的是,若没有溢出,add( ) 会把 0 赋值给 errno。
multiply( ) 在这方面跟 add( ) 一样。
 
 
 
#include<stdio.h>
#include<errno.h> /* errno, ERANGE */
 
 
/*
 * Returns the sum of a and b, with overflow and underflow check.
 * If overflow or underflow occurred, sets errno to ERANGE, else to 0.
 */
int add( int a, int b ) {

    int result = a + b;

    if( b > 0 && result > a || b <= 0 && result <= a )
        errno = 0;
    else
        errno = ERANGE;

    return result;
}
 
 
/*
 * Returns the proct of a and b obtained through repeated call of add( ).
 * Affects errno exactly as add( ) does.
 */
int multiply( int a, int b ) {

    int sign_of_a = 1,
        result = 0,
             i = 0;

    /* Keep the sign of multiplier off the loop sentinel. */
    if( a < 0 ) {
        sign_of_a = -1;
        a *= -1;
    }

    /* Have to reset errno here because it won't be updated if a is 0. */
    errno = 0;

    while( i++ < a ) {
        result = add( result, b );
        if( errno == ERANGE )
            break;
    }

    return result * sign_of_a;
}
 
 
 
int main( ) {

    int result;

    /* Operands too huge: sure overflow. */
    result = multiply( -5000000, 1374389539 );
    if( errno == ERANGE )
        perror( "Uh oh" );
    else
        printf( "%d\n", result );

    /* Small operands: safe. */
    result = multiply( 49, -972 );
    if( errno == ERANGE )
        perror( "Uh oh" );
    else
        printf( "%d\n", result );

}
 
 
 
当然,应付溢出的最佳方法还是防范:充分了解数据的范围,选择恰当的变量类型。

也许你正考虑改用不需要你担心整数类型溢出的语言。考虑过 Python 吗?
 
 
 

热心网友 时间:2023-10-29 17:18

把int型换成long型
一般来说long型占64位

热心网友 时间:2023-10-29 17:19

在现在的Windows平台下,长整型是long long或者__int64,是64位,而long应该是32位的,不是64的。

热心网友 时间:2023-10-29 17:19

长整型已经足够满足日常的使用了

热心网友 时间:2023-10-29 17:20

换长整型

热心网友 时间:2023-10-29 17:20

换长整型
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
抖音弹幕怎么关掉?怎么关闭抖音弹幕? 惠普LaserJet P3005D是否支持B5纸的双面打印? word打印出图片总是缺一部分怎么办-word打印图片不完整怎么解决_百度... 理想one哪里产的车辆? 抚州抚州ONE在哪里? one地址在哪里? 如何在图片上写字(如何在图片上添加文字) 网商贷为什么钱没到账 高级经济师职称怎么评 高级经济师需要评审吗 苹果六锁屏六位数密码忘记了有什么办法可以解锁的 食品稳定剂的安全性 上帝保佑美国 下载 CMOS运算放大器作为比较器翻转较慢 食品稳定剂的简介 c++ 溢出的int比较导致了死循环? 整型数据溢出问题,将int改成long还是溢出。。求解 在家里怎么做蛋糕的方法 32位int溢出的问题 食品中食品稳定性重要作用 TTL和cmos的比较器,哪种好,区别是什么? 有比较好的虚拟直播软件推荐吗? 盘点美国杀手电影经典电影,【免费高清】在线观看百度网盘资源 c语言int数据问题,关于是否溢出 苹果7为什么锁屏以后不能接消息? 苹果6手机解锁密码6位 跪求美国杀手电影,【免费高清】在线观看百度网盘资源 C语言中int型溢出怎么办 用unsigned long [ int ]都还是溢出该怎么办 想要存放11位的数字 我的手机是华为p30怎样才能与名爵zs互联? 一部美国电影大叔加一个小女孩开枪到处杀人的电影 上帝保佑美国主角在影院里看的电影叫什么 食品稳定剂EDTA的机理是什么?有什么毒副作用吗? 姚素英简介 为什么c语言对符号整型溢出没有规范定义 《上帝保佑美国》、《狂暴2:资本的惩罚》、《恶魔的崛起》、《帝国的毁灭》这四部欧美电影你最喜欢看? 食品稳定剂是什么呀 怎么用 什么牌的好用呀 华为p30怎么连接手机优盘? 如何减小cmos比较器的输入失调电压 上帝保佑美国这电影主要想表达什么 为什么大豆多糖能作为食品的稳定剂? CMOS常用门电路中异或门及反相器的功能 如何评价电影《上帝保佑美国》 使比较器输出电压为0,我设计的比较器输入电压在低于阈值时不为零 各种食品稳定剂在乳制品中发挥的作用 以及具体内容 有谁知道的发个好的连接或者直接回答我 faceu激萌的延时拍摄怎么设置成七秒或10秒? 电压比较器 食品添加剂的主要作用有哪些 若自己设计555定时器,那里面的电压比较器用什么型号的好?原理图: 食品添加剂主要有什么作用 Faceu激萌怎么延时摄影?