for example:
struct A { char s[10]; } f() {
struct A ret;
scanf("%9s", ret.s);
return ret;
}
int main()
{
char *str = f().s;
puts(str);
}
is str
pointing to a valid string? or has it been freed?
If it's safe, then where is the string data stored? the stack frame of main?
is
str
pointing to a valid string? or has it been freed?
No. It has not been freed in the sense a call to free
or similar routine is performed, but its lifetime ends after the initializer f().s
is evaluated.
This is a rare case of an object with temporary lifetime. The function returns a value that is not an lvalue, and that is true whether the function is implemented using a compound literal as in your original code or using an automatic object as in the current code. In either case, the function returns a value that has structure type; it does not return a normal object with one of the ordinary lifetimes.
C 2018 6.2.4 8 specifically addresses this case, a non-lvalue expression with structure type that contains an array:
A non-lvalue expression with structure or union type, where the structure or union contains a member with array type (including, recursively, members of all contained structures and unions) refers to an object with automatic storage duration and temporary lifetime. Its lifetime begins when the expression is evaluated and its initial value is the value of the expression. Its lifetime ends when the evaluation of the containing full expression ends…
In char *str = f().s;
, f().s
is a full expression (an expression that is not contained in any other expression). So, when evaluation of this full expression completes, the object’s lifetime ends, and the memory used for it is no longer reserved in the C model. So, when puts(str);
is executed, the C standard does not guarantee that str
points to memory containing the data the function produced or that it is a valid pointer at all.
If the code were puts(f().s);
, that would be okay, because then f().s
would be inside a larger expression, and its lifetime would continue until the puts
finished.