这是MinGW的错误吗?

时间:2010-06-16 07:48:22

标签: c++ c mingw

我一直试图通过Code :: Blocks:

在我的MinGW上执行这个程序
#include <string.h>
#include <math.h>
#include <stdio.h>
#define N 100
int p[N];
int pr[N];
int cnt;

void sieve()
{
   int i,j;
   for(i=0;i<N;i++) pr[i]=1;
   pr[0]=pr[1]=0;

   for(i=2;i<N;i++)
      if(pr[i])
        {
         p[cnt]=i; cnt++;
         for(j=i+i;j<=N;j+=i) pr[j]=0;
        }

  }

int main(){
    sieve();
    int i;
    for(i=0;i<cnt;i++)
       printf("%d ",p[i]);
    puts("");
   printf("Total number of prime numbers : %d",cnt);
  return 0;
}

在我的系统上,输出为:

7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
素数总数:22

这完全是疯了,因为我完全确定算法的实现。

所以我决定在Ideone中尝试它,它提供正确的输出。任何人都可以指出原因吗?

我将其更改为N,但输出不会改变。

6 个答案:

答案 0 :(得分:6)

不,它实际上被称为Debanjan错误:-)看看 this

#define N 100
int p[N / 64];

在我看来,您只允许足够的空间在p数组中存储一个素数。这意味着,为p[X]X > 0可能会覆盖其他值。

这是可怕的未定义行为,这意味着任何都可能发生(包括它在Ideone情况下的工作)。

只需使用:

int p[N];

声明数组。我很确定不会有超过100个小于或等于100的素数: - )

答案 1 :(得分:5)

您的代码中有两个重要的错误。

一个是你的p数组太小了,所以你要写下它的结尾。这是未定义的行为,但在您使用它的平台上会覆盖pr数组的开头。这对输出没有影响,因为您要覆盖的位置在您在筛子中测试的位置之前。

另一个是你还在写pr数组的末尾:

        for(j=i+i;j<=N;j+=i) pr[j]=0;

此循环将pr[N]设置为零,这不在pr的末尾。在MinGW中,这是cnt存储的位置,因此每次iN时,cnt都会设置为零。当N为100时,i==2i==5会发生这种情况,因此您的结果会在五次之前丢失素数。 IdeOne似乎将cnt放在与pr相关的其他位置,因此它不会被覆盖。这就是为什么你用不同的编译器得到不同的输出。

将数组p的大小更改为N,或者仅对筛选和输出使用一个数组,并将第18行中的<=更改为<,这样就不会注销结束它

int p[N];
int *pr = p; // reuse the array

答案 2 :(得分:2)

您的数组p只有一个元素,因为您使用整数除法100/64声明它。

将其更改为

int p[N];

或具有至少25个元素的东西。

答案 3 :(得分:1)

没有。我不相信在这种情况下会有一个MinGW错误。

您的应用程序中存在错误。正如之前提到的那样, p 数组只有只有1个元素。 (处理整数值时,100/64 = 1)。

这意味着当您在 p [1]或p [2]或p [3] (超出数组范围)之后访问时,您将在 p <之后实际访问区域内存/ em>这是 pr 数组。

使用Ideone我相信阵列的内存区域可能距离更远,而不是像MinGW那样一个接一个(这只是一个假设)。

答案 4 :(得分:0)

数组p太小,您将超出它并写入pr

变化:

int p[N / 64];

为:

int p[N / 2];

Foonote:永远不会因为你看到一个你无法立即解释的问题而假设编译器错误。 99.999%的时间它你的错误 - 你还没有找到它。

答案 5 :(得分:0)

100/64是1.所以p只有一个元素 - p [0]。当您访问p [1],p [2]等时,您开始覆盖pr数组中的元素。这会产生错误的结果。

这是你程序中的一个错误,而不是一个mingw bug。