Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can we return char* from function?

Tags:

c++

scope

Here is a piece of C++ code that shows some very peculiar behavior. Who can tell me why strB can print out the stuff?

char* strA()
{
    char str[] = "hello word";
    return str;
}

char* strB()
{
    char* str = "hello word";
    return str;
}

int main()
{ 
    cout<<strA()<<endl;  
    cout<<strB()<<endl;
}
                      
                                                                                                                                                            
like image 260
Caiyi Zhou Avatar asked Jun 05 '26 23:06

Caiyi Zhou


2 Answers

Why does strB() work?

A string literal (e.g. "a string literal") has static storage duration. That means its lifetime spans the duration of your program's execution. This can be done because the compiler knows every string literal that you are going to use in your program, hence it can store their data directly into the data section of the compiled executable (example: https://godbolt.org/z/7nErYe)

When you obtain a pointer to it, this pointer can be passed around freely (including being returned from a function) and dereferenced as the object it points to is always alive.

Why doesn't strA() work?

However, initializing an array of char from a string literal copies the content of the string literal. The created array is a different object from the original string literal. If such array is a local variable (i.e. has automatic storage duration), as in your strA(), then it is destroyed after the function returns.

When you return from strA(), since the return type is char* an "array-to-pointer-conversion" is performed, creating a pointer to the first element of the array. However, since the array is destroyed when the function returns, the pointer returned becomes invalid. You should not try to dereference such pointers (and avoid creating them in the first place).

like image 187
ph3rin Avatar answered Jun 07 '26 13:06

ph3rin


String literals exist for the life of the program.

String literals have static storage duration, and thus exist in memory for the life of the program.

That means cout<<strB()<<endl; is fine, the returned pointer pointing to string literal "hello word" remains valid.

On the other hand, cout<<strA()<<endl; leads to UB. The returned pointer is pointing to the 1st element of the local array str; which is destroyed when strA() returns, left the returned pointer dangled.


BTW: String literals are of type const char[], char* str = "hello word"; is invalid since C++11 again. Change it to const char* str = "hello word";, and change the return type of strB() to const char* too.

String literals are not convertible or assignable to non-const CharT*. An explicit cast (e.g. const_cast) must be used if such conversion is wanted. (since C++11)

like image 26
songyuanyao Avatar answered Jun 07 '26 11:06

songyuanyao