I am having a truly bizarre problem with my code here. It works (seemingly) when I use manual print statements to output the values of int *primesArr, but if I try to do so with a for loop it fails. I ran it through gdb and find that it crashes right around where I set the next cell in the array to value ‘k’, which only occurs when a number is prime. The first iteration is successful (i.e. 2 is set to primesArr[0]) and then the program Segfaults when trying to increment the array. But this only happens when using a for-loop. When I create individual print statements, my program works as expected. I’m not sure how/why I am accessing memory that hasnt been appropriated when using a for-loop. I’m sure I’ve performed some amateur mistake somewhere, and it probably has something to do with how I’m passing my pointer… but I cannot determine its exact root. I’d appreciate any help and thank you in advance.
#include<stdio.h>
int genPrimes(int seed, int *test){
int inNumPrimes=0;
for(int k=0; k<=seed; k++){//k is number being checked for primeness
int cnt=0;
for(int i=1; i<=k; i++){//'i' is num 'k' is divided by
if(k%i == 0){
cnt++;
if(cnt > 2){
break;
}
}else{
}
}
if(cnt == 2){
printf("%i IS PRIME\n",k);
*test=k;
test++;//according to gdb, the problem is somewhere between here
inNumPrimes++;//and here. I'd wager I messed up my pointer somehow
}
//printf("%i\n",k);
}
return inNumPrimes;
}
int main(){
int outNumPrimes=0;
int *primesArr;
int n = 0;
n=20;
outNumPrimes=genPrimes(n, primesArr);
printf("Congratulations! There are %i Prime Numbers.\n",outNumPrimes);
//If you print using this for loop, the SEGFAULT occurs. Note that it does not matter how high the limit is; its been set to many values other than 5. It will eventually be set to 'outNumPrimes'
//for(int a=0; a<5; a++){
//printf("%i\n",primesArr[a]);
//}
//If you print the array elements individually, the correct value--a prime number--is printed. No SEGFAULT.
printf("%i\n",primesArr[0]);
printf("%i\n",primesArr[1]);
printf("%i\n",primesArr[2]);
printf("%i\n",primesArr[3]);
printf("%i\n",primesArr[4]);
printf("%i\n",primesArr[5]);
printf("%i\n",primesArr[6]);
printf("%i\n",primesArr[7]);
//
return 0;
}
Output with manual statements:
$ ./a.out
2 IS PRIME
3 IS PRIME
5 IS PRIME
7 IS PRIME
11 IS PRIME
13 IS PRIME
17 IS PRIME
19 IS PRIME
Congratulations! There are 8 Prime Numbers.
2
3
5
7
11
13
17
19
Now with the for loop:
$ ./a.out
2 IS PRIME
Segmentation fault
The line
Declares
primesArras a pointer variable but doesn’t allocate any memory for it. Since thegenPrimes()function expects to treat it as an empty array that will be filled with primes, you can allocate memory inmain()before callinggenPrimes():or
In both cases, however, you must guarantee that
MAX_PRIMESis large enough to hold all of the primes thatgenPrimes()finds, otherwise the code will generate an error just as it does now.Other hints:
1: Complexity
The only reason
cntis necessary is thatkis divisible by1andk. If you changeto
then both of those cases are eliminated, and the loop can exit as soon as it finds a value of
ifor whichk%i == 0.2: Efficiency
The test
is still quite inefficient for two reasons. First, there’s no need to test every even number; if
k > 2and(k % 2) == 0, thenkcannot be prime. So you can eliminate half of the tests by checking explicitly for 2 (prime) or divisibility by 2 (not prime), and then usingBut you can make this still more efficient, because you can stop after reaching
sqrt(k). Why? Ifkis divisible by some numberi, then it must also be divisible byk/i(becausei * k/i=k). And ifi > sqrt(k), thenk/i < sqrt(k)and the loop would already have exited. So you need onlyIf
sqrt()isn’t available, you can use3: Style
Just a simple thing, but instead of
you can simply write