简体   繁体   中英

Returning array from function (C)

I'm extremely new to C programming, and am going through some tutorials. One thing that stumped me is with returning a pointer to an array. I've cut down the example from https://www.tutorialspoint.com/cprogramming/c_return_arrays_from_function.htm to best illustrate my point.

#include <stdio.h>

int * getRandom( ) {

   static int  r[10];
   int i;

   for ( i = 0; i < 10; ++i) {
      r[i] = i;
      printf( "r[%d] = %d\n", i, r[i]);
   }
   return r;
}

int main () {
   int *p;
   int i;
   p = getRandom();
   for ( i = 0; i < 10; i++ ) {
      printf( "*(p + %d) : %d\n", i, *(p + i));
   }
   return 0;
}

As one would expect, this prints

r[0] = 0
r[1] = 1
r[2] = 2
r[3] = 3
r[4] = 4
r[5] = 5
r[6] = 6
r[7] = 7
r[8] = 8
r[9] = 9
*(p + 0) : 0
*(p + 1) : 1
*(p + 2) : 2
*(p + 3) : 3
*(p + 4) : 4
*(p + 5) : 5
*(p + 6) : 6
*(p + 7) : 7
*(p + 8) : 8
*(p + 9) : 9

But when you change

   static int  r[10];

to

   int  r[10];

it instead prints

r[0] = 0
r[1] = 1
r[2] = 2
r[3] = 3
r[4] = 4
r[5] = 5
r[6] = 6
r[7] = 7
r[8] = 8
r[9] = 9
*(p + 0) : 0
*(p + 1) : 1980517315
*(p + 2) : -1164399724
*(p + 3) : 4199040
*(p + 4) : 4199040
*(p + 5) : 2285568
*(p + 6) : 19
*(p + 7) : 6356668
*(p + 8) : 8
*(p + 9) : 6356940

and I have no idea why. The only thing I can think of is that for some reason the compiler is reading the array cells as different data types, but I doubt that's right.

The static keyword is used to "remember" the value of r in the next call. If you remove it, then the memory allocated for r is flushed when the function returns, so you're just returning garbage.

When you have static int r[10]; , the memory for storing the array is allocated at compile-time, and everything works as expected.

When you instead have int r[10] , you are allocating your array on the run-time stack frame, which becomes invalid when the function call returns, and then gets overwritten by the next function call, so you see garbage.

The reason is that when you call getRandom() without a static array declaration, the array falls out-of-scope once the getRandom() function returns. This means that your pointer may no longer 'point' to r, because r is essentially discarded.

In order to return from getRandom() correctly, you would need to dynamically allocate your memory using malloc , for example:

int * getRandom( ) {
  int *r = NULL;
  r = malloc(sizeof(int) * 10); /* Create room for 10 integers*/
  if (r == NULL) {
    printf("Error: Could not allocate space\n");
    return NULL;
  }
  int i;
  for ( i = 0; i < 10; ++i) {
    r[i] = i;
    printf( "r[%d] = %d\n", i, r[i]);
  }  
  return r; /* Returns a pointer to r*/
}

int main () {
  int *p;
  int i;
   p = getRandom();
   if (p == NULL) {
     /*Error state*/
     return 1;
   }
   for ( i = 0; i < 10; i++ ) {
     printf( "*(p + %d) : %d\n", i, *(p + i));
   }
   free(p); /* Free the memory we allocated*/
  return 0;
}

Note how we must free the memory we allocated (otherwise we would have memory leaks). Also note that we must handle the NULL case, where we could not allocate the memory necessary.

Excepting by a few cases, an array in a expression always decays to the address of its first element.
This pointer is the value returned by the function.
The array itself, as an object living in memory, in general dies after the function execution finished.
So, the memory address pointed by the pointer that the function returned is not guaranteed to preserve the array, and it could have garbage instead.
The static declaration preserves the array object, but still your function have returned a pointer to the head of the array and not the array itself.
It is bad practice to return a pointer to an inner static object of a function, because you are allowing to any user of your function to change the values of the array from outside of the function in umpredictable ways.
If you want to return a complete array, as a value, perhaps you should define a struct type containing an array field, in this way:

  typedef struct {  int sub[10]; } wrappedarray_t;
  wrappedarray_t getRandom(void) {
         wrappedarray_t r;
         // sentences....
         return r;
   }
   wrappedarray_t p = getRandom();
   printf("0th element: %d\n", p.sub[0]);

because you're using a locally allocated piece of data; once the program goes out of scope, then all the data you saved to it is thrown out and it'll return garbage values.

In this situation, you can do two things:

either malloc() a pointer-array OR use the static array and return one of them.

ANOTHER option you can do is to put an array buffer in the function parameters so the data is copied to that buffer.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM