首页 文章

使用long int避免溢出是一个好习惯吗?

提问于
浏览
2

假设我已经声明了以下变量:

some_dataType a,b,c;  //a,b,c are positive
int res;
res=a+b-c;

并且我已经获得了变量 res 不能跨越整数限制的信息 . 为了避免从 a+b-c 中的表达式 a+b 溢出,我有以下选项 -

  • 将a,b,c声明为long int

  • (a-c) b

  • (long int) (a b-c)//或其他类型的投射

我的问题是以上哪项是好的做法 . 另外,为了摆脱这一切,我更喜欢做选项1.但它可能会增加程序的内存大小(虽然不适用于此程序,但适用于大型应用程序) .
假设:long int大于int谢谢@Retired Ninja

2 回答

  • 0

    没有简单,通用,可移植的方法来避免整数溢出 .

    使用更宽的整数类型不是一般解决方案,因为 intlong 类型在某些系统上的大小相同's no guarantee that there is a wider integer type. It' . 32位系统通常会产生 intlong 32位;甚至一些64位系统也做同样的事情 . 一些64位系统同时生成 intlong 64位 .

    你写了:

    并且我已经获得了变量res不能跨越整数限制的信息 .

    最好小心术语 . 虽然类型名称 int 显然是单词"integer"的缩写,但单词不是同义词 . 在C和C中, int 只是几种整数类型中的一种;其他包括 unsigned charlong long .

    大概你的意思是 res 的值不得超出 int 类型的范围,即 INT_MININT_MAX .

    如果您使用 long long 作为结果,则可能会避免溢出;然后,您可以将结果与值 INT_MININT_MAX 进行比较,如果 intlong long 仍为64位,则可采取适当的纠正措施 . 你用它做什么取决于你的代码需要多么可移植 .

    事实之后,您无法安全地检查有符号整数加法或减法是否溢出 . 带符号算术的溢出会导致未定义的行为 . 通常结果会结束,但原则上您的程序可能会在您有机会检查结果之前崩溃 .

    某些编译器可能会提供执行安全签名算术的函数,并告诉您是否存在溢出 . 请参阅编译器的文档 .

    在执行操作之前,有多种方法可以测试操作数 . 它们很复杂,而且我懒得弄清楚细节,但简单地说:

    • 如果 + 的操作数具有相反的符号,或者如果一个操作数是 0 ,则添加是安全的 .

    • 如果两个操作数都为正,则如果 x 不超过 INT_MAX - y ,则添加是安全的 .

    • 如果两个操作数均为负数,则如果 y 不小于 INT_MIN - y ,则添加是安全的 .

    我不保证以上内容是完全正确的*我只是把它写在了我的头顶上),但在大多数情况下,它可能比它的 Value 更多的努力 .

  • 4

    信任但要验证:

    assert(a > 0);
    assert(b > 0);
    assert(c > 0);
    assert((long)a - (long)c + (long)b <= INT_MAX);
    
    int res = a - c + b;
    

相关问题