简体   繁体   中英

Returning Array from function in C

For some reason, my function is only returning the first element in my array and I cannot figure out why the rest of the array goes out of scope. The function takes two integer arrays, adds their respective elements, and puts the sum into a third array which is returned.

Here is my code:

#include <stdio.h>
/* count digits, white space, others */

int *sumarrays(int arr1[], size_t arr1len, int arr2[], size_t arr2len);

void main() {

    int arr1[10];
    size_t arr1len = 10;
    int arr2[10] = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 };
    size_t arr2len = 10;
    int i;

    int *x;

    arr1[0] = 2;
    arr1[1] = 3;
    arr1[2] = 2;
    arr1[3] = 2;
    arr1[4] = 2;
    arr1[5] = 2;
    arr1[6] = 3;
    arr1[7] = 2;
    arr1[8] = 2;
    arr1[9] = 2;

    //printf("%d\t%d\t%d\n", arr1, *arr1, *(arr1 + 1));
    x = sumarrays(arr1, arr1len, arr2, arr2len);

    for (i = 0; i < 10; i++) {
        printf("Array1: %d\tArray 2: %d\tX = %d\n", arr1[i], arr2[i], x[i]);

    }

    //return 0;
}

int *sumarrays(int arr1[], size_t arr1len, int arr2[], size_t arr2len) {
    int i;
    int total[10];

    for (i = 0; i < 10; i++) {
        total[i] = *(arr1 + i) + *(arr2 + i);

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

    printf("\n");
    return total;
}

Here is the output:

4   5   4   4   4   4   5   4   4   4   
Array1: 2   Array 2: 2  X = 4
Array1: 3   Array 2: 2  X = 1974388256
Array1: 2   Array 2: 2  X = -161927102
Array1: 2   Array 2: 2  X = 2686628
Array1: 2   Array 2: 2  X = 8670801
Array1: 2   Array 2: 2  X = 0
Array1: 3   Array 2: 2  X = 27
Array1: 2   Array 2: 2  X = 2686540
Array1: 2   Array 2: 2  X = 4
Array1: 2   Array 2: 2  X = 2686916

The first line is the sum array elements from within the function. The remainder is what happens in the main().

What am I missing?

*edit* ANSWERED

Thank you everyone for the help! I actually learned C and C++ a while ago but have recently started to go back and fine tune my knowledge. Really appreciate all the help.

The main answers were

1) Statically allocate memory (using the static keyword)

2) Dynamically allocate memory (using malloc())

3) Make the variable global

4) Pass the result total() as an argument to the function so it doesn't go out of scope.

You are doing stack allocation for your array, and stack-allocated storage goes away when a function returns. Use heap allocation instead.

Change

int total[10];

to

int* total = malloc(10*sizeof(int)) .

of course, that means you must also free the memory after you are done with it. In this case, before the return 0; in main, you need to

free(x);

my function is only returning the first element in my array and I cannot figure out why the rest of the array goes out of scope.

No, it returns a pointer to the first element - and the entire array goes out of scope. Any data you see that happens to remain as it was in the function is by luck rather than judgement, and you cannot use it as it is released for use by other functions.

Arrays are not first class data types in C - you cannot return an array by copy.

The normal solution is to have the array owned by the caller and to pass its address and size to the function.

int* func( int* arr, int arrlen )
{
    // write to arr[0] to arr[arrlen-1] ;

    return arr ;
}

int main()
{
    int array[256] ;
    func( array, sizeof(arr)/sizeof*(*arr) ) ;
}

Other less common and generally ill-advised possibilities are either to return a struct containing the array (a struct is a first class data type), but to do that is somewhat inefficient in many cases, or to dynamically allocate the array within the function, but it is not a particularly good idea since the caller has the responsibility of freeing that memory and may not be aware of that responsibility - it is a recipe for a memory leak.

You can't return a pointer to an automatic local variable . total is an automatic local variable and it doesn't exist after function body executed.

Pointer to static local variable or dynamically allocated variable can be returned. Change
int total[10]; to

int *total = malloc(10 * sizeof(int));

The problem is that when sumarrays returns, the total array ceases to exist 1 , so the pointer value that main receives is no longer valid. In short, you cannot return arrays from a function like this.

You have several options.

The first (and IMO the preferred option) is to pass the total array as one of your parameters, and make the caller responsible for setting aside enough memory:

void sumarrays(int arr1[], size_t arr1len, int arr2[], size_t arr2len, int *total, size_t totallen) 
{
  ...
  for (i = 0; i < totalLen; i++) {
      total[i] = *(arr1 + i) + *(arr2 + i);
  ...
}

#define ARRLEN 10

int main( void )
{
  ... 
  int x[ARRLEN];
  ...
  sumarrays( arr1, ARRLEN, arr2, ARRLEN, x, ARRLEN);

In this method, the caller ( main ) is responsible for knowing how big the target array needs to be and setting aside the memory for it. The helps decouple the sumarrays function from main because it doesn't have to rely on information that isn't explicitly specified by the parameter list (such as the array sizes). With this approach, you're not limited to arrays of size 10.

A second option is to declare total such that it doesn't go away after sumarrays exits. You can do this by either declaring it at file scope (as in ryyker's answer), or by declaring it static within the sumarrays function:

int *sumarrays(int arr1[], size_t arr1len, int arr2[], size_t arr2len) {
    int i;
    static int total[10];
    ...

With this approach, the total array will be allocated at program startup and held until the program terminates. What makes this approach less desireable is that you have only a single instance of that total array, which is shared across all calls to sumarrays . The function is no longer re-entrant ; if sumarrays called another function that called sumarrays , then whatever the first call had written to total would be clobbered by the second call (the strtok library function has this problem, which has caused much heartburn in the past). Your code obviously doesn't have this problem, but it's something to be aware of. Don't declare things static if you don't have to.

The final option is for sumarrays to allocate the memory for total dynamically (as in haccks' and merlin2011's answers). That avoids the re-entrancy issue, but now you have to deal with memory management. C isn't your mother and won't clean up after you, so any memory you allocate with malloc or calloc you have to release with free 2 .


1. Logically speaking, anyway; the memory is obviously still there, but it's been made available for the rest of the system to use, and has been overwritten in the time it took for your program to return to the main function.

2. Most platforms will reclaim dynamically allocated memory when the program exits, but a few (admittedly older, oddball platforms) may not. Also, for long-running programs (servers, daemons, etc.), you have to be very careful to release any memory you allocated and no longer need, otherwise you will eventually run out.

I agree with every other answer regarding automatic (stack) and heap memory. All good approaches, however global variables on the stack are also an option . It is important to note that it was not that you chose to use stack memory, but that it was also local in scope . Locally scoped automatic variables die when the function that created them returns. However, globally scoped variables, also stored using stack memory, live for the duration of your program, and therefore provide an alternative approach to solve your problem...

A one line change will result in your code running, change your local copy of total (automatic scope) to a global:

int total[10];//Put this here,  outside of any function block in same file, i.e. (will give it global scope)
//note, commented this in function below

int *sumarrays(int arr1[], size_t arr1len, int arr2[], size_t arr2len) {
    int i;
    //int total[10];//move this to global scope


    for (i = 0; i < 10; i++) {
        total[i] = *(arr1 + i) + *(arr2 + i);

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

    printf("\n");
    return total;
}

With this approach , global scope of variable allows your return to be successful. The array total keeps it's existence on stack until program exits.

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