1

I realize that variables declared in a function call are pushed onto the stack and once the function reaches its end the local variables declared onto the stack are popped off and go into lala land.

The thing I don't undertstand is that if I declare a pointer in a function I can return the pointer with no compiler complaint, whereas with an array it does give me a warning.

Here is an example of what I'm referring to:

char * getStringArray();
char * getStringPointer();

int main(){
        char * temp1 = getStringPointer();
        char * temp2 = getStringArray();
        return 0;
}
char * getStringPointer(){
        char * retString = "Fred";
        return retString;
}
char * getStringArray(){
        char retString[5] = {'F', 'r','e','d','\0'};
        return retString;
}

During compilation it throws a "returning address of local variable" warning about getStringArray(). What confuses me is that I've been told that referencing an array solely by its name(like retString, no[])refers to its address in memory, acting like a pointer.

Arrays can be handy and there are many times I would like to use an array in a function and return it, is there any quick way around this?

As I referred to in a comment, will this work? I'm guessing malloc allocates to heap but so its fine. I'm still a little unclear of the difference between static data and data on the heap.

char * getStringPointer(){
        char * retString = (char *)malloc(sizeof(char)*4+1);
        *(retString+0) = 'F';
        *(retString+1) = 'r';
        *(retString+2) = 'e';
        *(retString+3) = 'd';
        *(retString+4) = '\0';
        return retString;
}
5
  • what is lala land? Pointers are just pointers that point to an address in memory. What warnings is being thrown regarding getStringArray(), its not surprising though, you have declared and defined a array of five characters and return that back, but the definition does not match the prototype which is declared and defined as pointer to char. Commented May 19, 2016 at 22:54
  • @t0mm13b An array of char decays to a pointer to char. So, language-lawyer-wise, there's nothing illegal about getStringArray. It is, of course, pointing to memory that goes out scope, though. Commented May 19, 2016 at 22:58
  • You should never depend on a C compiler to warn of possible errors. That is what lint and similar utilities are for and even they don't catch everything problematic. Commented May 19, 2016 at 23:03
  • @JonHarper Of course I know that the first element of the array decays into a pointer of type T! But, look at the definition of both the variable and prototype. That would certainly raise a warning there. The variable is array, the prototype is function returning pointer to type char. Commented May 19, 2016 at 23:08
  • What compiler are you using and what is the warning level? Commented May 19, 2016 at 23:11

4 Answers 4

4

getStringPointer is allocating a pointer on the stack, then returning that pointer, which points to the string 'Fred\0' somewhere in your executable (not on the stack). getStringArray allocates space for 5 chars on the stack, assigns them 'F' 'r' 'e' 'd' and '\0', then returns a pointer to the address of 'F', which is on the stack (and therefore invalid after the function returns).

There are two ways round it: either you can malloc some space for your array on the heap, or you can make a struct that contains an appropriately sized array and return that. You can return numerical, pointer and struct types from functions, but not arrays.

Sign up to request clarification or add additional context in comments.

12 Comments

Once getStringArray returns, retString is popped off the stack and accessing the returned pointer would be UB
Indeed. I think the OP understands that pointers to the stack are no longer valid after a function returns (from the 1st para in the question), but they don't understand that the string constant "Fred" is not on the stack.
Ok so what I'm gathering from the multiple answers and comments is that declaring a pointer within a function is global, but declaring an Array is not. It is interesting that you do no suggest making the array static. Any reason for that?
Also, when I think "Global variable" I think not only of a variable allocated to the heap but a variable that has a scope greater than just the function it is declared in. By declaring the Array static would I be able to access the data outside of the function(not counting the returned value where the function was originally called.) by name?
The pointer itself isn't global, it's the string constant. The memory address where "Fred" resides is written when you program is loaded, and can be accessed at any time (though the only place you can get a pointer to it is on the line it's declared on). If you declare a variable static in a function its name is only available in that function.
|
3

"Fred" is an unnamed global, so it's not going away, and returning a pointer to it is safe. But getStringArray() is de-allocating everything that pointer points to. That's the difference.

1 Comment

@Khaines0625 you can, of course, have a global array as well... its down to storage modifiers that can affect the return value.
0

The array is unambiguously a pointer to stack-local memory so the compiler is certain that's what you are leaking, so that's why you get the warning.

Just make the array static and both the warning and the lifetime restriction will vanish.

Now, the pointer could be pointing to something static or in the heap (in your case it actually was static) and so it's not obvious from looking at just that one expression whether you are leaking something stack-local or not. That's why you don't get the warning when you return a pointer, regardless of whether it's a safe return or not. Again, the static storage class will save you. Your string constant happens to be static, so that works fine.

2 Comments

You said "static or in the heap." I was under the impression that static variables are stored in the heap? Is that not true?
It's not true. Static data is stored in a segment of the executable that exists in the actual image file itself. In C, the heap is strictly used for objects allocated via malloc(3). For one thing, all initialization would then have to be dynamic, and therefore slow.
0

By adding a static modifier to the variable retString and returning back a pointer will resolve the issue.

char * getStringArray(){
        static char retString[5] = {'F', 'r','e','d','\0'};
        return retString;
}

That will return the appropriate value.

Notice how its still treated as a pointer, because the first element of the array is decayed into a pointer of type T, in this case, char. This will make the compiler happy as it matches the prototype declaration of the function itself as defined at the start of the source.

See ideone sample

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.