Thread: Initializing int array at runtime, Prime Sieve

  1. #1
    Registered User javaeyes's Avatar
    Join Date
    Feb 2012
    Posts
    153

    Initializing int array at runtime, Prime Sieve

    I have written a simple Sieve of Eratosthenes to generate all the primes from 2 to n. Right now it's all in main. I want to refactor it into a function, getPrimes(), so that I will have just one line of code, namely:

    int primes[n???] = getPrimes(n);

    primes[] should be an array of only the primes, not a boolean array of whether prime[i] is prime or not. e.g. prime[0]=2 , prime[1]=3 ... The problem is I won't know until the sieve has executed, how many primes there will be between 2 and n. So I have 2 questions:

    1) How can I initialize primes[] without knowing how many elements it will contain?

    2) I know I can't just return an array from a function, but if I return a pointer, can the values stored in the array be overwritten because it was created within a function?

  2. #2
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    1) You can't. You can make it a reasonable size (like sqrt(n)) and not worry about the wasted space, or you can use dynamic memory allocation (see below).
    2) Not really.. you can return a pointer from a function, true. But the pointer can't point to a local array from within the function (the variable will have gone out of scope), it can only point to dynamically allocated memory. And if it's dynamically allocated, you'd just use the pointer directly rather than copying the data into an array, because you'd already have what you needed!

    Okay, so the best approach is probably to have getPrimes() use malloc() to dynamically allocate memory for the array, since only getPrimes() knows how big the array should be. Actually, it doesn't even know how big the array should be, but it could allocate some memory and grow it if necessary. Example:
    Code:
    int *getPrimes(int *count, int max) {
        int size = 10;  // this keeps track of how many elements are allocated
        int *array = malloc(size * sizeof(*array));
        *count = 0;  // this keeps track of how many elements are used, so *count <= size at all times
    
        for( /* ... */ ) {
            // assume x needs to be added to the array.
            if(*count + 1 > size) {
                // not enough space.
                size *= 2;
                array = realloc(array, size * sizeof(*array));
            }
            array[*count] = x;
            *count ++;
        }
        return array;
    }
    
    int count;
    int *data = getPrimes(&count, n);
    // now, data is an array of count elements.
    As you can see, it's a bit complicated. But it's worth trying, to get the hang of it, because dynamic memory allocation is very powerful. I suggest you read up on it a bit. Doubling the size of the array is standard practice to make the amortized insertion cost constant (basically, if you always add like +10 every time, it gets very expensive with large arrays). Also, malloc() and realloc() return NULL if there's no more memory available, so you should handle that... but in this example I've glossed over that detail since it's complex enough as it is.

    [edit] BTW, sizeof(*array) is the same as sizeof(array[0]), which in this case would be sizeof(int). It's useful to specify sizeof(*array) however, in case the type of array changes from int* to float* or something in the future. Also, sizeof(*array) and sizeof(array[0]) are compile-time expressions, so your program isn't slowed down at all by doing this. [/edit]
    Last edited by dwks; 09-04-2012 at 12:10 PM.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  3. #3
    Registered User javaeyes's Avatar
    Join Date
    Feb 2012
    Posts
    153
    This actually makes perfect sense to me, thanks so much for your reply. One question though, once I finally have the the data how can I loop through it without knowing how many elements it contains? count has been increased in the function and not returned. I know that the array values will always be ints, can I do something like:
    int imax = sizeof(data) / sizeof(int)?
    and then (for i = 0 ; i < imax ; i++)?

    Thank you again. Much appreciated

  4. #4
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    Nope, with just a pointer you have no way of knowing how many elements are in the array it points to. That's why I passed in count as a pointer to the function; it's modified within the function, and then you can read its value after the function has returned. Essentially, the only way to return two values at once [without using structures] is to "return" one of the values through a passed-by-reference parameter. So you really do have int *array and int count in the end.

    sizeof(data) would give the size of an int*, a pointer to int, probably 4 or 8 (32- or 64-bit). The idiom sizeof(data)/sizeof(*data) only works on true arrays, unfortunately. Strangely enough I was just writing about that over in a different thread: Arrays vs pointers
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  5. #5
    Registered User javaeyes's Avatar
    Join Date
    Feb 2012
    Posts
    153
    Aha, that is really nice, perfect, thank you.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Prime Sieve Help
    By sellefrancais in forum C Programming
    Replies: 2
    Last Post: 04-03-2011, 03:04 PM
  2. problem initializing a double array for large array
    By gkkmath in forum C Programming
    Replies: 4
    Last Post: 08-25-2010, 08:26 PM
  3. Idea for a fast and efficient prime sieve
    By Sebastiani in forum General Discussions
    Replies: 2
    Last Post: 06-21-2010, 06:26 AM
  4. Replies: 2
    Last Post: 12-24-2009, 02:41 AM
  5. Prime Sieve Optimization
    By rt454 in forum C++ Programming
    Replies: 9
    Last Post: 05-30-2008, 09:22 PM