简体   繁体   中英

Returning array declared in function returns address of local variable in C?

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

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

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.

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.

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

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