计算C中

时间:2016-05-05 06:36:11

标签: c

我正在用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而不是很长时间?

4 个答案:

答案 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)

如前所述,您提供的代码调用未定义的行为。因此它可以计算你想要的东西或发射核导弹......

未定义行为的原因是您要引发的有符号整数溢出,以“测试”数据类型的范围。

如果您只是想知道intlong和朋友的范围,那么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;

Ideone link

假设有两个补码用于signed和,则无符号类型只有一个值比符号类型多一个。有关详细信息,请参见§6.2.6.2/ 2(例如N1570)。