Question

Suppose I want to write (in C99) the following function:

NAME: primes
INPUT: an integer n > 0
OUTPUT: int array filled with the prime numbers in range [2, n]

How can I return such an array from my function? Is that possible?


Note that I don't want the caller to allocate an n * sizeof(int) array that I'll fill with 0 (composite) and 1 (primes).

I can't just return a pointer to the array, because the caller has no way to know how long the array is:

int * primes(int n)
{
    int * arr = malloc(n * sizeof(int));
    // do stuff
    return arr;
} 

int main(void)
{
    int * arr = primes(100);
    printf("%lu \n", sizeof arr); // prints 8
}

and I can't change the signature like this:

int (*primes(int n))[LENGTH]  

because LENGTH is unknown at compile time.


I read somewhere something like "to return a struct with the array is an horrible idea", and, well... that was my last idea.

What's the best practice in cases like this?

Was it helpful?

Solution

If the function that you call must decide the actual number of elements that it needs to allocate, you should pass a pointer to the allocated length along with the rest of the parameters, like this:

size_t actual_length;
int *arr = primes(100, &actual_length);
if (arr == NULL) {
    ... // Report an error
}
for (size_t i = 0 ; i != actual_length ; i++) {
    printf("%d\n", array[i]);
}

The primes would then look like this:

int *primes(int count, size_t *actual_length) {
    size_t primes_needed = ...
    int *res = malloc(sizeof(*res)*primes_needed);
    *actual_length = primes_needed;
    // Do calculations, perhaps some reallocs
    // Don't forget to reassign *actual_length = ... on realloc
    ...
    return res;
}

OTHER TIPS

When an array is allocated with malloc you can't request its size with sizeof. Common practice in these situations is to return the size of the array and assign it to a pointer-pointer given as an argument. Like this:

int primes(int n, int ** arr){
    int length = n;
    *arr = malloc(length * sizeof(int));
    // do stuff...
    // if *arr is realloc()ed update length
    return length;
}

and then call it like this:

int * arr;
length = primes(100, &arr);

An example of a standard function that does this is fread. It takes as an argument an array and the number of elements (and size of the elements) it should read. It then returns the number of elements it actually read, which may be less, if for example the end of the file was reached.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top