1

I tried this:

int* test()
{
    static int states[2]= {4,7};
    return states;
}

And called it like this:

int* values = test();

But it only seems to return the first value - 4 - and not the whole array.

I tried to do it exactly as I saw in other examples so I'm confused as to why it doesn't work. I'm using the STM32cubeIDE to write and compile, if that makes a difference.

1
  • Your code is returning a pointer to the array. This looks valid because the array is marked as static. values[0] will be 4 and values[1] will be 7. How are you checking what is returned? Please post a Minimal, Reproducible Example. Commented Oct 28, 2020 at 11:29

3 Answers 3

4

Normal arrays can't be returned from a function because their lifetime ends when the function returns, the behavior for accessing one of these local arrays outside the scope of the function is undefined.

In your particular case this is possible because your array has static storage duration.

In C a function can only return one element, so to return an array you must return a pointer which can contain the address of the first element of that array. And that's what you're doing in your code. You can access both values by correctly indexing the returned pointer i.e. values[0] and values[1].

Unfortunately this is not without its issues, the size of the array is not known by the caller and you can't safely index it because you don't know its bounds.

There are ways solve this which are not all that complicated once you get used to them. Most notably defining a global size for the array1, using a structure containing the size of the array and a pointer to the array itself2, or passing pointers to the size and/or the array as arguments of the function3.

1. Using a global variable that stores its size:

#define SIZE 2

int *test()
{
    static int states[SIZE] = {4, 7};
    return states; //returns a pointer to the first element of the array
}

int main()
{
    int* values = test(); // values is now pointing to the array
    
    for(size_t i = 0; i < SIZE; i++){
        printf("%d ", values[i]); //indexing is similar to a local array
    }
}

2. Using a struct to store both the size and a pointer to the array:

typedef struct{ //structure to hold the data
    int *array;
    size_t size;
} array_struct;

array_struct test()
{  
    static int states[2] = {4, 7};
    array_struct array = {.array = states, .size = 2}; //assing pointer and size
    return array; //return the structure
}

int main()
{
    array_struct values = test(); //assing the structure to a local
    
    for(size_t i = 0; i < values.size; i++){ //use the size passed
        printf("%d ", values.array[i]);
    }
}

Output:

4 7 

Option 3 is laid out in Bathsheba's answer.

Sign up to request clarification or add additional context in comments.

5 Comments

ok, that makes sense to me.... why is it so complicated to do this? is it not a normal thing to return more than one value from a function? My C skills are very basic - I used to use global variables for everything and i'm trying to rewrite stuff to work better but things like this make me think im doing something which isn't normal practice
@prune You can use structures to return multiple things from functions.
@prune, in C it is not, only one value can be returned, so to return an array the way to do it is to return a pointer to it's first element, it's the way the language is designed. That said there are ways to do it that are not all that complicated when you get used to them, most notably, passing the size as argument, defining a global size, or passing a structure containing the size of the array and a pointer to the array itself.
It should be noted that it's absolutely possible to return a ''normal'' array (array located in stack-memory), however it's undefined behaviour, as the returned pointer points to memory which is not ''reserved for it''.
@gkhaos, it was kind of implied in the first paragraph, but it's definitely worth explicitly mentioning the consequences of such action, I edited it.
1

You get back a pointer to the first element of the array due to the decay of the array type to a pointer type.

You obtain the other elements by pointer arithmetic.

Unfortunately though all size information is lost so you don't know at the call site how many elements you have. One way round that would be to change the function to

void test(int** array, size_t* length)

with *array = states and *length = sizeof(states) / sizeof(states[0]) in the function body.

Comments

1

How do I correctly return an array from a function?

You don't because you cannot. Read the C11 standard n1570.

(since as return values, arrays are decayed to pointers)

In practice, you could use a flexible array member in your struct and return some malloc-ed pointer to that struct. You then need a documented convention about who will free that pointer.

Read about C dynamic memory allocation. For more details and example code, see this answer.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.