After reading this article I understand the methods for returning multiple values using structs or pointers (the first two). However, after describing the third method (using a temp array), the author writes:
We should not use this approach as the variable information is not passed to the caller function. For example, we’re using the array’s index to retrieve the values of our variables. Also, note that we have to allocate the array dynamically in a heap. If we use the static array, it ceases to exist when we exit the function, and accessing it inside the caller function will result in undefined behavior.
This is the code example the author provides:
#include <stdio.h>
#include <stdlib.h>
// Function to return multiple values using an array
int* initialize()
{
// Important: Dynamically allocate memory
int *temp = (int*) malloc(sizeof(int) * 3);
*temp = 10;
*(temp 1) = 20;
*(temp 2) = 30;
return temp;
}
// Return multiple values from a function in C
int main(void)
{
int a, b, c;
int *arr = initialize();
a = arr[0];
b = arr[1];
c = arr[2];
printf("a = %d, b = %d, c = %d", a, b, c);
// free memory
return 0;
}
I don't understand what the author means, because I tried this method in a small program I wrote and it seems to works just fine, i.e. I can access the returned array's elements in the caller function. Why is this not recommended?
CodePudding user response:
The referenced text is unclear and confusing at best. At worst, outright wrong.
We should not use this approach as the variable information is not passed to the caller function.
It's unclear what "variable information" means here. The actual values is getting back to the caller so that's not the problem. Maybe "variable information" is supposed to mean something like "information about number of variables" but that's unclear.
For example, we’re using the array’s index to retrieve the values of our variables.
Yes, well, of cause... If the values are being sent back in a (dynamic allocated) array, we have to use array indexing to get them. That's obvious and not really a problem.
Also, note that we have to allocate the array dynamically in a heap.
Finally something clear and correct.
If we use the static array, it ceases to exist when we exit the function, and accessing it inside the caller function will result in undefined behavior.
Here it's very unclear what "the static array" refers to. There is no static array in the code. It seems to be refering to some code only available in the authors head...
If the author is thinking about code like:
int temp[3]; // Instead of malloc
then the author is correct. But... that's not a static array so ....
If the author is thinking about code like:
static int temp[3]; // Instead of malloc
then the author is wrong. Due to static
this array can be accessed from the caller.
So again... very confusing...
To answer your question:
Why is this not recommended?
Well, some concerns could be:
Dynamic allocation is an expensive operation. So don't use it unless you have a good reason.
Returning dynamic allocated memory from function and relying on the caller to free it later on is a source of many memory leak bugs. So avoid doing that.
BUT...
Good pratice rules nearly always comes with exceptions.
For instance consider a function that returns a rather huge and unknown number of results. For such a function it can be fine to return a pointer to dynamic allocated memory. But you would also need to return the actual number of results. It could look like:
int foo(int ** a)
{
// Generate results and use code like
*a = malloc(.. a lot ..)
...
// Perhaps some realloc(.. even more ..)
...
return number_of_results; // or perhaps -1 on error
}
int * a;
int results = foo(&a);
if (results > 0)
{
....
for (int i=0; i < results; i)
{
// Do something with a[i]
...
}
....
free(a);
}
...
CodePudding user response:
If we use the static array, it ceases to exist when we exit the function, and accessing it inside the caller function will result in undefined behavior.
It is rubbish. static
automatic array will still exist after the function return. It is because such array has static storage duration The function will be not reentrant.
The author probably meant automatic storage duration array.
Undefined behaviour (UB):
int *foo(void)
{
int array[10];
/* ... */
return array;
}
No undefined behaviour:
int *bar(void)
{
static int array[10];
/* ... */
return array;
}