如何在不溢出的情况下提取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?的副本,我不得不反对,因为这是一个如何,而不是一个为什么问题。
答案 0 :(得分:3)
格式字符串%d
中的printf
转换说明符将相应的参数转换为带符号的十进制整数,在这种情况下,会溢出int
类型。 C标准特别提到有符号整数溢出是未定义的行为。您应该做的是在格式字符串中使用%u
。此外,您还需要分别为stdio.h
和stdlib.h
函数的原型添加标题printf
和abs
。
#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_MIN
与LONG_MIN
和LLONG_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 int
或long long int
个变量中。