Q:

C - Most efficient method of filtering an integer array

I've successfully implemented Eratosthenes' sieve (I know there are faster methods for finding primes, this is just a learning exercise) for prime numbers in C, but I have not found a satisfying way of filtering my returned array of primes for zeros.  To illustrate, when run my program returns this:
$ ./primesieve
Input search limit > 100
0 0 2 3 0 5 0 7 0 0 0 11 0 13 0 0 0 17 0 19 0 0 0 23 0 0 0 0 0 29 0 31 0 0 0 0 0 37 0 0 0 41 0 43 0 0 0 47 0 0 0 0 0 53 0 0 0 0 0 59 0 61 0 0 0 0 0 67 0 0 0 71 0 73 0 0 0 0 0 79 0 0 0 83 0 0 0 0 0 89 0 0 0 0 0 0 0 97 0 0
$
I need some method of filtering the zeros. I'm assuming there is some algorithm more efficient than merely iterating over the return array and copying out the nonzero elements to a second array before printing out the answer, but I haven't been able to find one or come up with one myself.  The integer array is malloc'd on the heap, by the way.
Here's the code.
Edit: Final code pasted in with zero_filter() method implemented.
Edit2: completely forgot the sieve only requires to search up to sqrt(n)... fixed in code below.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <math.h>
#include "dbg.h"

void init_array(int sieve[], int size) {

    int i;

    for(i = 0; i < size; i++) {
        sieve[i] = i;
    }

    sieve[1] = 0;
}

int prime_filter(int sieve[], int size, int root) {

    int i, j;
    int zero_count = 2;

    for(i = 2; i < root; i++) {
        if(sieve[i] != 0) {
            for(j = 2 * i; j < size; j += i) {
                if(sieve[j] != 0) {
                    sieve[j] = 0;
                    zero_count++;
                }
            }
        }
    }

    return zero_count;
}

void zero_filter(int sieve[], int final_array[], int size) {

    int i;
    int j = 0;

    for(i = 0; i < size; i++) {
        if(sieve[i] != 0) {
            final_array[j] = sieve[i];
            j++;
        }
    }
}

void print_array(int final_array[], int size) {

    int i;

    for(i = 0; i < size; i++) {
        printf("%d ", final_array[i]);
    }
}

void destroy_arrays(int *sieve, int *final_array) {

    if(sieve) {
        free(sieve);
    }
    if(final_array){
        free(final_array);
    }
}

int main(int argc, char *argv[]) {

    check(argc == 1, "No input required");

    int size, root, rv;  // upper limit on search, return value

    printf("Input search limit > ");
    rv = scanf("%d", &size);
    check(rv != EOF, "Input error on scanf().");
    check(rv != 0, "Input error, expected integer");

    root = (int) sqrt(size) + 1;

    int *sieve, *final_array;
    int zero_count, new_size;

    sieve = malloc(sizeof(int) * size);
    check(sieve != NULL, "Memory allocation error");

    init_array(sieve, size);
    zero_count = prime_filter(sieve, size, root);

    new_size = size - zero_count;

    final_array = malloc(sizeof(int) * (new_size));
    check(final_array != NULL, "Memory allocation error");

    zero_filter(sieve, final_array, size);
    print_array(final_array, new_size);
    destroy_arrays(sieve, final_array);

    printf("\n");
    return 0;

error:
    return -1;
}

A:

I think you need function like std::remove in C++. It "removes" elements in-place. Have a look: std::remove
If you not familiar to C++ and templates, here adopted code:
int *remove(int *first, int *last, int val)
{
  int *result = first;
  while (first!=last) {
    if (!(*first == val)) {
      *result = *first;
      ++result;
    }
    ++first;
  }
  return result;
}

And you can call it with this code:
int array[n];
int *end = remove(array, array + n, 0);
size_t not_removed_size = end - array; // values in range [array[0], ... array[not_removed_size]) are non-zeros.

