Reputation: 77941
I have a hard time understanding the difference between these three:
const char * f() {
return "this is a test";
}
const char * g() {
const char * str = "test again";
return str;
}
const double * h() {
const double a = 2.718;
return &a;
}
I get a warning for the h()
, as warning: address of local variable ‘a’ returned
. Which makes sense, but I do not understand why the compiler (gcc -Wall
) is ok with the f()
and g()
function.
f()
or g()
gets deallocated?Upvotes: 3
Views: 2682
Reputation: 3335
These strings are physically and permanently placed inside your data memeory, so their addresses are permanent. The automatic variable is on the stack, so it will disappear the moment you return from the call.
Upvotes: 0
Reputation: 59607
In the function h
, a
is a local variable that won't exist after the function returns. You're returning a pointer to that variable, and so dereferencing the pointer outside the function is incorrect, and undefined behavior.
In f
and g
you're returning literal strings. Literal strings have static storage: they aren't allocated on the stack, and they'll exist beyond the lifetime of the functions.
In the definition of g
:
const char *g()
{
const char *str = "test again";
return str;
}
str
is a local variable, but it's a pointer to non-local - statically allocated - memory. It's that address that you're returning, not a reference to the local variable.
Consider another definition of g
:
const char *g()
{
const char str[] = "test again";
// incorrect: can't use str after the return:
return str;
}
Now g
has the same problem as your function h
, and when compiling it you should see the same warning about returning the address of a local variable.
Upvotes: 1
Reputation: 23265
String literals are not stored in the local stack frame. They live in a fixed place in your executable. Contrast:
const char * g() {
const char * p = "test again";
return p;
}
with
const char * g() {
const char a[] = "test again";
return a;
}
In the former, the return value points to a fixed place in your executable. In the latter, the return value points to (a now invalid location in) the stack.
Upvotes: 8
Reputation: 361254
const char * g() {
const char * str = "test again";
return str;
}
This doesn't return the address of local variable. The variable is str
, and therefore it address should be &str
which would be different from str
itself:
std::cout << (void*) str << std::endl;
std::cout << (void*) &str << std::endl; //address of str (local variable)
They would print different values!
So a more apt example would be this:
const char ** g() {
const char * str = "test again";
return &str; //difference!
}
Now it returns the address of the local variable. A good compiler may issue warning for this.
Another example would be this:
const char * g() {
const char str[] = "test again"; //difference!
return str; //same as before
}
Now even though you return str
which doesn't seem to be the address of the local variable, it may give warning, as in this case, the value of str
and &str
would be exactly same! Try printing these now:
std::cout << (void*) str << std::endl;
std::cout << (void*) &str << std::endl; //address of str (local variable)
They would print the same value!
Upvotes: 3
Reputation: 8831
The string literals aren't local variables. The string equivalent of the third function is this
const char * f() {
const char str[] = "this is a test";
return str;
}
Upvotes: 1
Reputation: 9161
Storage allocation for string literals is static, that is why you don't get a warning.
Try this and you will get undefined behavior:
const char* getFoo()
{
std::string foo("hi");
return foo.c_str();
}
Because the string foo made a copy of the literal string.
Upvotes: 0
Reputation: 55887
It's string literals.
n3337 2.14.5/8
Ordinary string literals and UTF-8 string literals are also referred to as narrow string literals. A narrow string literal has type “array of n const char”, where n is the size of the string as defined below, and has static storage duration
Upvotes: 6