Categories
c c++ local-variables pointers

How to access a local variable from a different function using pointers?

63

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?

5

  • 1

    Hard to know the best suggestion for your intention, here. But you might like to read up on shared pointers (shared_ptr and friends). They provide some of the nice properties of garbage collected languages by doing reference counting. But different, so use caution.

    Dec 31, 2010 at 13:59

  • I vote to re-open this and use it as a canonical duplicate for questions of the nature “I’m getting a crash when returning a pointer to local variable, why?”, rather than that other classic canonical duplicate which is rather for “I’m not getting a crash, why not?”

    – Lundin

    Jan 14, 2016 at 11:09


  • @Lundin kinda problematic that this has both C and C++.

    Nov 6, 2018 at 16:02

  • @AnttiHaapala There’s nothing unique to C++ in the question, but unfortunately there are C++ answers so the tag has to stay.

    – Lundin

    Nov 6, 2018 at 16:34

  • If used on an embedded system then dynamically allocating memory is dangerous, so there are 3 possibilities, make the variable global, make it static, or pass in a pointer to the variable from the calling routine.

    Mar 16, 2021 at 7:45

60

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.

8

  • 2

    Or you could declare it static.

    – user1481860

    Dec 31, 2010 at 13:47

  • 3

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

    Dec 31, 2010 at 13:51

  • 3

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

    – user1481860

    Dec 31, 2010 at 13:57

  • 2

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

    Dec 31, 2010 at 14:29

  • 5

    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.

    Dec 31, 2010 at 19:44

19

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).

0

    8

    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;
    }
    

    7

    • 1

      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.

      – Shaihi

      Dec 31, 2010 at 13:40


    • @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.

      – user418748

      Dec 31, 2010 at 13:42


    • 2

      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.

      Dec 31, 2010 at 13:42


    • Added a more “Correct” version.

      – user418748

      Dec 31, 2010 at 13:48

    • 2

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

      – jweyrich

      Dec 31, 2010 at 13:50