By Radek Simko


2010-12-31 13:27:55 8 Comments

May I have any access to a local variable in a different function? If so, how?

void replaceNumberAndPrint(int array[3]) {
    printf("%i\n", array[1]);
    printf("%i\n", array[1]);
}

int * getArray() {
    int myArray[3] = {4, 65, 23};
    return myArray;
}

int main() {
    replaceNumberAndPrint(getArray());
}

The output of the piece of code above:

65
4202656

What am I doing wrong? What does the "4202656" mean?

Do I have to copy the whole array in the replaceNumberAndPrint() function to be able to access it more than the first time?

9 comments

@Galik 2016-03-20 11:16:12

C++ solution:

"May I have any access to a local variable in a different function? If so, how?"

The answer is no, not after the function has ended. Local variables are destroyed at that point.

In C++ the way to deal with returning arrays is to manage them in a container like a std::array (fixed size) or a std::vector (dynamic size).

Eg:

void replaceNumberAndPrint(const std::array<int, 3>& array) {
    printf("%i\n", array[0]);
    printf("%i\n", array[1]);
    printf("%i\n", array[2]);
}

std::array<int, 3> getArray() {
    std::array<int, 3> myArray = {4, 65, 23};
    return myArray;
}

In the second function the returned value is optimized by the compiler so you don't pay the price of actually copying the array.

@CodesInChaos 2010-12-31 13:31:25

myArray is a local variable and as thus the pointer is only valid until the end of its scope (which is in this case the containing function getArray) is left. If you access it later you get undefined behavior.

In practice what happens is that the call to printf overwrites the part of the stack used by myArray and it then contains some other data.

To fix your code you need to either declare the array in a scope that lives long enough (the main function in your example) or allocate it on the heap. If you allocate it on the heap you need to free it either manually, or in C++ using RAII.

One alternative I missed (probably even the best one here, provided the array is not too big) is to wrap your array into a struct and thus make it a value type. Then returning it creates a copy which survives the function return. See tp1's answer for details on this.

@ruslik 2010-12-31 13:32:20

By trying to access it, you invoke undefined behavior.

@Oystein 2010-12-31 13:47:32

Or you could declare it static.

@Matteo Italia 2010-12-31 13:51:02

@Øystein: ... keeping in mind that the function would become potentially non-reentrant and non-thread-safe.

@CodesInChaos 2010-12-31 13:51:55

Making it static has quite different semantics, especially in multi threaded applications unless the content of the array is constant.

@Oystein 2010-12-31 13:57:19

Sure, but it is a way to solve the problem and should be pointed out, right?

@CodesInChaos 2010-12-31 14:29:19

Pointing it out is of course useful, but you need to point out the downsides too, so your first comment was a bit incomplete.

@R.. 2010-12-31 19:44:52

I would say recommending static as a solution to this problem is harmful and never helpful. For newbies, it becomes a formulatic band-aid in place of really understanding the problem and writing correct code, and later when somebody else inherits the newbie's code, they'll be horrified at all the nonsensical static variables all over the place.

@CodesInChaos 2011-01-01 11:35:27

@R.. If the data is immutable then there are use cases. Mutable global state on the other hand is dangerous and needs serious consideration before use.

@aquib23 2014-01-07 08:53:51

In this code you have used pointer to local objects but when a function returns all local variables goes out of scope. If you will allocate memory (using malloc() function for allocation) then no data will be lost or overwrite.

int* getArray(int size) {
    int *myArray = (int*)malloc(size*sizeof(int));
    myArray[0] = 4;
    myArray[1] = 65;
    myArray[2] = 23;
    return myArray;
}

int main() {
    int i;
    int *vector = getArray(3);
    for(i=0;i<3;i++)
    {
        printf("%i\n",vector[i]);
    }
    getch();
    return 0;
}

This code will print all the array elements and no overwritten will be happened.

@Mat 2014-01-07 11:23:48

Your code leaks... not a good example.

@aquib23 2014-01-10 16:08:00

Thanks Mat for telling me...

@tp1 2011-01-02 23:15:14

Right way to do this is as follows:

struct Arr {
   int array[3];
};
Arr get_array() {
   Arr a;
   a.array[0] = 4;
   a.array[1] = 65;
   a.array[2] = 23;
   return a;
}
int main(int argc, char **argv) {
   Arr a = get_array();
   for(size_t i=0; i<3; i++)
       printf("%d\n", a.array[i]);
   return 0;
}

To understand why you need to do this, you need to know how sizeof(array) works. C (and thus c++) tries hard to avoid copying the array, and you need the struct to go past that. Why copying is needed is because of scopes -- the get_array() function's scope disappears and every value still needed from that scope will need to be copied to calling scope.

@sherrellbc 2013-10-02 16:07:20

I know this was quite some time ago, but would you not either need to typedef or allocate the structure like struct Arr a?

@melpomene 2018-09-13 06:05:18

@sherrellbc In C, yes. In C++ struct Foo { ... }; automatically defines the types struct Foo and Foo, no typedef needed.

@jweyrich 2010-12-31 14:15:17

Local variables go out of scope upon return, so you can't return a pointer to a local variable.

You need to allocate it dynamically (on the heap), using malloc or new. Example:

int *create_array(void) {
    int *array = malloc(3 * sizeof(int));
    assert(array != NULL);
    array[0] = 4;
    array[1] = 65;
    array[2] = 23;
    return array;
 }
 void destroy_array(int *array) {
     free(array);
 }
 int main(int argc, char **argv) {
     int *array = create_array();
     for (size_t i = 0; i < 3; ++i)
         printf("%d\n", array[i]);
     destroy_array(array);
     return 0;
 }

Alternatively, you can declare the array as static, keeping in mind the semantics are different. Example:

int *get_array(void) {
    static int array[] = { 4, 65, 23 };
    return array;
 }
 int main(int argc, char **argv) {
     int *array = get_array();
     for (size_t i = 0; i < 3; ++i)
         printf("%d\n", array[i]);
     return 0;
 }

If you don't know what static means, read this question & answer.

@Muggen 2010-12-31 13:36:44

Try something like that. The way you do it "kills" myArray cause if it locally defined.

#include <stdio.h>
#include <stdlib.h>

void replaceNumberAndPrint(int * array) {
 printf("%i\n", array[0]);
 printf("%i\n", array[1]);
 printf("%i\n" , array[2]);
 free(array);
}

int * getArray() {
 int * myArray = malloc(sizeof(int) * 3);
 myArray[0] = 4;
 myArray[1] = 64;
 myArray[2] = 23;
 //{4, 65, 23};
 return myArray;
}

int main() {
 replaceNumberAndPrint(getArray());
}

More : http://www.cplusplus.com/reference/clibrary/cstdlib/malloc/

Edit: As Comments correctly pointed out: A better way to do it would be that :

#include <stdio.h>
#include <stdlib.h>

void replaceNumberAndPrint(int * array) {
    if(!array)
        return;

    printf("%i\n", array[0]);
    printf("%i\n", array[1]);
    printf("%i\n" , array[2]);
}

int * createArray() {
    int * myArray = malloc(sizeof(int) * 3);

    if(!myArray)
        return 0;

    myArray[0] = 4;
    myArray[1] = 64;
    myArray[2] = 23;
    return myArray;
}

int main() {
    int * array = createArray();
    if(array)
    {
        replaceNumberAndPrint(array);
        free(array);
    }
    return 0;
}

@Shaihi 2010-12-31 13:40:11

Be sure to comment this "feature" REALLY good if you use this in your code. Allocating memory by one function and releasing it by another is VERY dangerous unless properly documented and even then is prone to memory leaks! Would be better to allocate the array in main and release it when it is no longer needed.

@Muggen 2010-12-31 13:42:08

@Shaihi, this is true, also this piece of code is very naive cause it doesn't check whether malloc() allocated successfully. But I think OP will understand the whole point.

@CodesInChaos 2010-12-31 13:42:34

While this works it's ugly. You should change the function names(getArray => createArray) to describe their behavior better. And having replaceNumberAndPrint delete the source array doesn't seem like a good idea to me. I'd rather separate deleting and printing into two different functions.

@Muggen 2010-12-31 13:48:29

Added a more "Correct" version.

@jweyrich 2010-12-31 13:50:59

@Muggen: don't you prefer array[i] instead of *(array+i)?

@Muggen 2010-12-31 13:51:42

@jwerich, hm, ok I will fix. That sounds better. It could raise more questions than answers.

@CodesInChaos 2010-12-31 13:55:01

Now the code looks good for c. In C++ there are better solutions, but those are probably beyond the scope of this question.

@Prasoon Saurav 2010-12-31 13:34:10

Your code invokes Undefined Behaviour because myArray goes out of scope as soon as getArray() returns and any attempt to use (dereference) the dangling pointer is UB.

@James Gaunt 2010-12-31 13:32:00

You can't access a local variable once it goes out of scope. This is what it means to be a local variable.

When you are accessing the array in the replaceNumberAndPrint function the result is undefined. The fact it appears to work first time is just a fortunate coincidence. Probably the memory location you are pointing to is unallocated on the stack and is still correctly set for the first call, but the call to printf then overwrites this by pushing values onto the stack during its operation which is why the second call to printf displays something different.

You need to store the array data on the heap and pass a pointer, or in a variable that remains in scope (e.g. a global or something scoped within the main function).

@John Pickup 2010-12-31 13:31:59

myArray goes out of scope as soon as you leave getArray. You need to allocate space for it on the heap instead.

Related Questions

Sponsored Content

11 Answered Questions

[SOLVED] How do function pointers in C work?

  • 2009-05-08 15:49:17
  • Yuval Adam
  • 736321 View
  • 1092 Score
  • 11 Answer
  • Tags:   c function-pointers

10 Answered Questions

[SOLVED] Improve INSERT-per-second performance of SQLite?

35 Answered Questions

10 Answered Questions

19 Answered Questions

[SOLVED] Can a local variable's memory be accessed outside its scope?

7 Answered Questions

[SOLVED] size_t vs. uintptr_t

  • 2009-09-23 05:59:41
  • Chris Lutz
  • 54565 View
  • 242 Score
  • 7 Answer
  • Tags:   c pointers size-t

5 Answered Questions

[SOLVED] Typedef function pointer?

  • 2010-11-28 04:50:25
  • Jack Harvin
  • 343180 View
  • 394 Score
  • 5 Answer
  • Tags:   c++ c pointers typedef

1 Answered Questions

[SOLVED] returning pointer of a local variable to main() function

  • 2017-10-28 06:42:37
  • Shlok Srivastava
  • 85 View
  • -3 Score
  • 1 Answer
  • Tags:   c

14 Answered Questions

[SOLVED] How many levels of pointers can we have?

  • 2012-04-10 10:34:17
  • Parag
  • 42262 View
  • 424 Score
  • 14 Answer
  • Tags:   c++ c pointers

4 Answered Questions

[SOLVED] Pointer to local variable in C++

Sponsored Content