首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >取整数的绝对值

取整数的绝对值
EN

Stack Overflow用户
提问于 2016-02-07 08:41:39
回答 6查看 1.6K关注 0票数 20

考虑以下程序(C99):

代码语言:javascript
复制
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>

int main(void)
{
    printf("Enter int in range %jd .. %jd:\n > ", INTMAX_MIN, INTMAX_MAX);
    intmax_t i;
    if (scanf("%jd", &i) == 1)
        printf("Result: |%jd| = %jd\n", i, imaxabs(i));
}

现在,据我了解,这包含了很容易触发的、未定义的行为,如下所示:

代码语言:javascript
复制
Enter int in range -9223372036854775808 .. 9223372036854775807:
 > -9223372036854775808
Result: |-9223372036854775808| = -9223372036854775808

问题:

  1. 当用户输入坏数字时,这是否真的是未定义的行为,如“允许代码触发任何代码路径,而这是任何让编译器想象的代码”?或者是其他的味道-没有完全定义?
  2. 一个迂腐的程序员如何才能避免这种情况,而不做出任何没有标准保证的假设呢?

(有几个相关的问题,但我没有找到一个回答上面的问题2,所以如果你建议重复,请确保它回答。)

EN

回答 6

Stack Overflow用户

发布于 2016-02-07 09:34:10

如果不能表示imaxabs的结果,那么如果使用两个补码,则行为是不确定的。

7.8.2.1 imaxabs函数

  1. imaxabs函数计算整数j的绝对值。如果不能表示结果,则行为未定义。221)

221)最负数的绝对值不能用两种补语来表示。

不作任何假设且总是被定义的检查是:

代码语言:javascript
复制
intmax_t i = ... ;
if( i < -INTMAX_MAX )
{
    //handle error
}

(如果使用补码或符号大小表示,则不能使用此if语句,因此编译器可能会发出无法到达的代码警告。代码本身仍然是定义的和有效的。)

票数 10
EN

Stack Overflow用户

发布于 2016-02-07 08:52:32

在两个补码系统上,获得最负值的绝对值确实是未定义的行为,因为绝对值将超出范围。编译器无法帮助您,因为UB是在运行时发生的。

防止这种情况的唯一方法是将输入与类型的最负值进行比较(在您显示的代码中是INTMAX_MIN)。

票数 4
EN

Stack Overflow用户

发布于 2016-02-07 22:38:14

因此,计算整数的绝对值会在一种情况下调用未定义的行为。事实上,虽然可以避免不明确的行为,但在一种情况下不可能给出正确的结果。

现在考虑整数乘以3:这里我们有一个更严重的问题。此操作在所有情况下调用2/3 3rds中未定义的行为!对于三分之二的int值x,要找到一个具有3x值的int是不可能的。这是一个比绝对值问题更严重的问题。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35251410

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档