[英]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
的存儲位置,因此,每次i
除N
, cnt
都將設置為零。 當N
為100時,這發生在i==2
和i==5
,因此您從結果中損失的質數比5大。 IdeOne似乎相對於pr
將cnt
放在其他位置,因此它不會被覆蓋。 這就是為什么您使用不同的編譯器獲得不同的輸出的原因。
將數組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.