簡體   English   中英

這是一個MinGW錯誤嗎?

[英]Is this a MinGW bug?

我一直在嘗試通過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,但輸出未更改。

不,它實際上是一個Debanjan錯誤:-)看看這個

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

在我看來,您只允許足夠的空間在p數組中存儲一個質數。 這意味着對於X > 0寫入p[X]可能會覆蓋其他值。

這是可怕的未定義行為,這意味着任何事情都可能發生(包括它在Ideone情況下的工作)。

只需使用:

int p[N];

聲明數組。 我很確定不會小於或等於100的素數不超過100 :-)

您的代碼中有兩個重要的錯誤。

一種是您的p數組太小,因此您要注銷它的末尾。 這是不確定的行為,盡管在使用的平台上它會覆蓋pr數組的開始。 這對輸出沒有影響,因為要覆蓋的位置早於篩中要測試的位置。

另一個是您還要注銷pr數組的末尾:

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

此循環將pr[N]設置為零,該值不在pr的末尾。 在MinGW中,這是cnt的存儲位置,因此,每次iNcnt都將設置為零。 N為100時,這發生在i==2i==5 ,因此您從結果中損失的質數比5大。 IdeOne似乎相對於prcnt放在其他位置,因此它不會被覆蓋。 這就是為什么您使用不同的編譯器獲得不同的輸出的原因。

將數組p的大小更改為N,或者僅對篩子和輸出使用一個數組,然后將第18行中的<=更改為<這樣就不會注銷它的末尾。

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

您的數組p僅具有一個元素,因為您使用整數除法100/64

更改為

int p[N];

或至少包含25個元素的東西。

不。我不認為在這種情況下有MinGW錯誤。

您的應用程序中有一個錯誤。 正如人們先前提到的, p數組只有1個元素 (處理整數值時100/64 = 1)。

這意味着當您在p [1]或p [2]或p [3] (超出數組范圍)之后訪問時,您實際上將在p (即pr數組)之后訪問區域存儲器。

我相信,使用Ideone,陣列中的存儲區可能相隔更遠,而不是像MinGW情況那樣一個接一個地排列(這只是一個假設)。

數組p太小,您將覆蓋它並寫入pr

更改:

int p[N / 64];

至:

int p[N / 2];

Foonote:永遠不要僅僅因為看到了無法立即解釋的問題而承擔編譯器錯誤。 99.999%的時間是您的錯誤-您尚未找到它。

100/64為1。因此p只有一個元素-p [0]。 當您訪問p [1],p [2]等時,您將開始覆蓋pr數組中的元素。 產生錯誤的結果。

這是程序中的錯誤,而不是mingw錯誤。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM