我正在用C编写程序来计算不同数据类型的范围。请查看以下代码:
#include <stdio.h>
main()
{
int a;
long b;
for (a = 0; a <= 0; --a)
;
++a;
printf("INT_MIN: %d\n", a);
for (a = 0; a >= 0; ++a)
;
--a;
printf("INT_MAX: %d\n", a);
for (b = 0; b <= 0; --b)
;
++b;
printf("LONG_MIN: %d\n", b);
for (b = 0; b >= 0; ++b)
;
--b;
printf("LONG_MAX: %d\n", b);
}
输出结果为:
INT_MIN: -32768
INT_MIN: 32767
LONG_MIN: 0
LONT_MAX: -1
程序花了很长时间才打印出长值。我还在第三个循环中放置了一个printf来测试程序(这里没有提到)。我发现即使它变为正面,b也没有退出循环。
我使用了相同的计算方法。为什么它适用于int而不是很长时间?
答案 0 :(得分:3)
您使用的是错误的格式说明符。由于b
的类型为long
,因此请使用
printf("LONG_MIN: %ld\n", b);
事实上,如果你启用了所有警告,编译器可能会警告你,例如:
t.c:19:30: warning: format specifies type 'int' but the argument has type 'long' [-Wformat]
printf("LONG_MIN: %d\n", b);
答案 1 :(得分:2)
在C中,将有符号整数递减超过其最小值(并且类似于递增超过最大值)是undefined behaviour。你的程序可以做任何事情。
例如,gcc compiles your program to an infinite loop with no output。
正确的方法是:
#include <limits.h>
#include <stdio.h>
int main()
{
printf("INT_MIN = %d\n", INT_MIN);
// etc.
}
答案 2 :(得分:0)
在
printf("LONG_MIN: %d\n", b);
格式说明符是%d
,适用于整数(int
)。它应该更改为%ld
以打印长整数(long
),情况也是如此
printf("LONG_MAX: %d\n", b);
这些陈述应该是
printf("LONG_MIN: %ld\n", b);
&安培;
printf("LONG_MAX: %ld\n", b);
这种方法可能不适用于所有编译器(例如gcc),更简单的方法是使用limits.h。
同时检查Integer Limits。
答案 3 :(得分:0)
如前所述,您提供的代码调用未定义的行为。因此它可以计算你想要的东西或发射核导弹......
未定义行为的原因是您要引发的有符号整数溢出,以“测试”数据类型的范围。
如果您只是想知道int
,long
和朋友的范围,那么limits.h
就是您需要寻找的地方。但如果你真的想要......
[..]计算范围[..]
...出于某种原因,你可以使用相应类型的unsigned
变体(尽管请参见末尾的注释),并像这样计算最大值:
unsigned long calculate_max_ulong(void) {
unsigned long follow = 0;
unsigned long lead = 1;
while (lead != 0) {
++lead;
++follow;
}
return follow;
}
这只会导致无符号整数换行(从最大值到0),不被归类为未定义行为。根据上面的结果,您可以获得相应的签名类型的最小值和最大值,如下所示:
assert(sizeof(long) == sizeof(unsigned long));
unsigned long umax_h = calculate_max_ulong() / 2u;
long max = umax_h;
long min = - max - 1;
假设有两个补码用于signed和,则无符号类型只有一个值比符号类型多一个。有关详细信息,请参见§6.2.6.2/ 2(例如N1570)。