INT_MIN的绝对值

时间:2014-03-08 11:38:18

标签: 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;
}

吐出以下内容

INT_MAX: 2147483647
INT_MIN: -2147483648
abs(INT_MIN): -2147483648

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

至于这个问题是Why the absolute value of the max negative integer -2147483648 is still -2147483648?的副本,我不得不反对,因为这是一个如何,而不是一个为什么问题。

6 个答案:

答案 0 :(得分:3)

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

#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;
}

这会在我的32位计算机上输出:

INT_MAX: 2147483647
INT_MIN: -2147483648
absu(INT_MIN): 2147483648

答案 1 :(得分:2)

怎么样

printf ("abs(INT_MIN) = %ld", -((long int) INT_MIN));

或者,如果您的long不长于int

printf ("abs(INT_MIN) = %lld", -((long long int) INT_MIN));

或者,如果您准备接受abs(INT_MIN)总是INT_MAX + 1

printf ("abs(INT_MIN) = %u", ((unsigned int) INT_MAX ) + 1 );

答案 2 :(得分:2)

没有可移植的方法来将最负数的绝对值提取为整数。 ISO C标准说(§6.2.6.2¶2):

作为值位的每个位应具有与对象中相同位相同的值 相应无符号类型的表示(如果有符号中有M个值位) 无符号类型中的类型和N,则M≤N)。

注意它使用≤,而不是&lt;。

由于2的补码中的符号位的值为 - (2 M ,并且每个值位的值为之间的2的幂。 1 2 M-1 ,在 M = N 可以表示的实现上无法使用无符号整数2 N ,它只能代表 2 N -1 = 1 + 2 + ... + 2 N-1 的。

答案 3 :(得分:0)

在C中,只有函数int abs(int j)存在int版本。您可以在标题labs下使用其他功能stdlib.h。它的原型:long int labs(long int j);

#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): %ld\n", labs((long)INT_MIN));

    return 0;
}

答案 4 :(得分:0)

转换为下一个可用的更大整数类型应该这样做。但是你必须使用相应的abs变量(在这种情况下是llabs(...)

printf("llabs(INT_MIN): %lld\n", llabs((long long int)INT_MIN));

修改

您可以通过将INT_MINLONG_MINLLONG_MIN进行比较来检查下一个更大类型的内容。也许在你的情况下,long的演员阵容已经完成了。

printf("labs(INT_MIN): %ld\n", labs((long int)INT_MIN));

请注意,显式强制转换实际上是不必要的,因为函数本身会隐式地转换参数

答案 5 :(得分:-2)

首先,您需要#include <math.h>才能正确使用abs功能。

第二件事是,如果您想要实现的唯一目的是打印INT_MIN中定义的limits.h的绝对值,您可以将其打印为unsigned integer或作为long long integer,像这样:

printf( "abs(INT_MIN): %u\n", abs( INT_MIN ) );     // %u for unsigned int
printf( "abs(INT_MIN): %lld\n", abs( INT_MIN ) );   // %lld for long long int

因为你想拥有绝对值,绝对是无符号的,所以这应该没问题。

如果您不想加入math.h,可以像这样自行制作:

// ternary implementation of the function abs
printf( "abs(INT_MIN): %u\n", ( INT_MIN > 0 ) ? INT_MIN : -INT_MIN );

如果您想将其用于其他目的,则可以将abs( INT_MIN )值存储在unsigned intlong long int个变量中。