INT_MIN的绝对值

Mor*_*lde 9 c int integer-overflow

如何在INT_MIN不溢出的情况下提取绝对值?请参阅此代码以了解该问题:

#include <limits.h>
#include <stdio.h>
#include <stdlib.h>

int main(void) {
    printf("INT_MAX: %d\n", INT_MAX);
    printf("INT_MIN: %d\n", INT_MIN);
    printf("abs(INT_MIN): %d\n", abs(INT_MIN));

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

吐出以下内容

INT_MAX: 2147483647
INT_MIN: -2147483648
abs(INT_MIN): -2147483648
Run Code Online (Sandbox Code Playgroud)

我需要这个来检查一个int值是否大于零.

至于这个问题是重复的为什么最大负整数-2147483648的绝对值仍然是-2147483648?,我不同意,因为这是一个如何,而不是一个为什么问题.

aja*_*jay 5

%d格式字符串中的转换说明符将printf相应的参数转换为带符号的十进制整数,在这种情况下,该int类型会溢出。C 标准特别提到有符号整数溢出是未定义的行为。%u您应该做的是在格式字符串中使用。此外,您还需要分别包含函数原型的标题stdio.h和。stdlib.hprintfabs

#include <limits.h>
#include <stdio.h>
#include <stdlib.h>

// This solves the issue of using the standard abs() function
unsigned int absu(int value) {
    return (value < 0) ? -((unsigned int)value) : (unsigned int)value;
}

int main(void) {
    printf("INT_MAX: %d\n", INT_MAX);
    printf("INT_MIN: %d\n", INT_MIN);
    printf("absu(INT_MIN): %u\n", absu(INT_MIN));

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

这给出了我的 32 位机器上的输出:

INT_MAX: 2147483647
INT_MIN: -2147483648
absu(INT_MIN): 2147483648
Run Code Online (Sandbox Code Playgroud)

  • 请注意,这仍然会调用 UB;来自 `abs` 的 C99 标准:“*如果无法表示结果,则行为未定义。*” (11认同)
  • 这实际上是正确的还是由于实现定义的行为而恰好起作用 (4认同)
  • 每个在这里发表评论的人都需要去最顶部并阅读以下评论:“二补码中最小数的绝对值不存在。”来自 deviantfan。尝试将 INT_MIN 转换为无符号是无法表示的。正如在那条评论中,您需要描述您实际上想要在这里完成的任务 (2认同)