I have a problem understanding a solution for number theory problem from SPOJ Problem statement can be found here or down below.

The solution which I'm trying to understand can be found here or down below.

Problem Statement.

Peter wants to generate some prime numbers for his cryptosystem. Help him! Your task is to generate all prime numbers between two given numbers!

Input
The input begins with the number t of test cases in a single line (t&lt;=10). In each of the next t lines there are two numbers m and n (1 &lt;= m &lt;= n &lt;= 1000000000, n-m&lt;=100000) separated by a space.

Output
For every test case print all prime numbers p such that m &lt;= p &lt;= n, one number per line, test cases separated by an empty line.

Example
Input:
2
1 10
3 5

Output:
2
3
5
7

3
5

Solution

Concept: The idea behind solution here is to generate all the prime numbers that could be factors of numbers up to the maximum endpoint 1 billion. That square root happens to be around 32000. Using this array, do a bounded Sieve of Eratosthenes only in the range requested. 

#include &lt;stdio.h&gt;
#include &lt;string.h&gt;
#include &lt;stdbool.h&gt;
#include &lt;math.h&gt;

int main() {
int primes[4000];
int numprimes = 0;

primes[numprimes++] = 2;
for (int i = 3; i &lt;= 32000; i+=2) {
    bool isprime = true;
    int cap = sqrt(i)+1;
    for (int j = 0; j &lt; numprimes; j++) {
        if (primes[j] &gt;= cap) break;
        if (i % primes[j] == 0) {
            isprime = false;
            break;
        }
    }
    if (isprime) primes[numprimes++] = i;
}

int T,N,M;
scanf("%d",&amp;T);

for (int t = 0; t &lt; T; t++) {
    if (t) printf("\n");
    scanf("%d %d",&amp;M,&amp;N);
    if (M &lt; 2) M = 2;

    int cap = sqrt(N) + 1;

    bool isprime[100001];
    memset(isprime,true,sizeof(isprime));

    for (int i = 0; i &lt; numprimes; i++) {
        int p = primes[i];

        if(p &gt;= cap) break;

        int start;

        if (p &gt;= M) start = p*2;
        else start = M + ((p - M % p) % p);

        for (int j = start; j &lt;= N; j += p) {
            isprime[j - M] = false;
        }
    }

    int start = (M % 2)?M:M+1;

    if (M == 2) {
        printf("2\n");
    }
    for (int i = start; i &lt;= N; i+=2) {
        if (isprime[i-M]) printf("%d\n",i);
    }
}
return 0;
}



I know how Sieve of Eratosthenes works and I also ran this program using pen and paper. It works fine but I 'm not able to understand why it works and how do I prove that this program and the algorithm used in it are right?
I spent hours but could not prove.
Any help would be appreciated.
A number is prime if it has no non-trivial factors. In order to check whether a number $n$ is prime, it suffices to check that it has no factors in the range $2,\ldots,\sqrt{n}$. In order to find all primes in $[a,b]$, we go over all primes in $2,\ldots,\sqrt{b}$ (using a list prepared ahead of time), and for each such prime $p$, we mark off all multiples of $p$ in $[a,b]$. After going over all such primes, the unmarked numbers in $[a,b]$ are prime.

How do we mark off all multiples of $p$ in $[a,b]$? We mark off the first multiple $p \lceil a/p \rceil$ (computed in a funny way in the code), if it happens to fall inside the interval (but not if this multiple happens to be $p$ itself!), and then we mark off the remaining multiples, by jumping in steps of $p$ until we fall off the interval $[a,b]$.