In foo_2()
, you're returning the address of a (non-static
) local variable. That address becomes indeterminate when the function returns, because the pointed-to object no longer exists -- thus the warning.
In foo_1()
, you're returning the value of a local variable. There's no problem at all doing that; it's no worse than:
int foo_3(void) {
int local = 42;
return local;
}
which returns the value of local
.
In foo_1()
, since the variable whose value you're returning happens to be a pointer, you could still invoke undefined behavior if that value were questionable. For example:
int foo_1a(void) {
char arr[] = "bar";
char *p = arr; // or equivalently, &arr[0]
return p;
}
Here you're still returning the value of a local variable (which is fine), but that value happens to be the address of another local variable, so the returned pointer value becomes invalid as soon as the function returns.
A compiler is less likely to warn about foo_1a
than about your foo_2
, because it's less likely to be able to determine that the value of p
when the return statement is executed is problematic. In fact the language does not require a diagnostic for this kind of thing. Compilers can do a reasonably good job of detecting and warning about some but not all instances of undefined behavior.
Bottom line: Your foo_1()
function is well behaved. The pointer value it returns is the address of a string literal, which has static storage duration (i.e., it exists for the entire lifetime of the program).
However, since modifying that static array has undefined behavior, it would be wise to return the address as a const char*
rather than as a char*
, so the caller is less likely to attempt to modify the string literal. The const
also serves as documentation for any human readers that the pointed-to value is not to be modified.