DiAvOl said:
That is exactly the reason I asked, to understand why it works for C99
and not for C89
I won't use such a construct in C89 of course, I'm trying to
understand (and I think i do understand now) why it works (or does
not!!) this way in C89
In C89/C90, the implicit conversion of an expression of array type to
a pointer to the array object's first element occurs only
when the array expression is an lvalue. Quoting the C90 standard:
Except when it is the operand of the sizeof operator or the unary
& operator, or is a character string literal used to initialize an
array of character type, or is a wide string literal used to
initialize an array with element type compatible with wchar_t, an
lvalue that has type "array of _type_" is converted to an
expression that has type "pointer to _type_" that points to the
initial element of the array object and is not an lvalue.
Your array expression "make_person().name" is not an lvalue, so the
conversion doesn't occur. It's unclear what happens next. I *think*
you're passing the array by value to printf, which normally isn't
possible; since printf is expecting a char* due to the "%s" format,
the behavior is undefined. But when you assign the result of
make_person() to the object p, the expression p.name *is* an lvalue,
the conversion does occur, and everything works.
C99 drops the requirement for the array expression to be an lvalue, so
the array-to-pointer conversion does occur, even for
"make_person().name". The problem, though, is that it's not at all
clear what "the array object" is. Arguably if there's no lvalue, then
there's no array object, and the standard's requirement is
meaningless.
C1X proposes to create an implicit temporary object in this case, so
"make_person().name" *is* an lvalue. It's been suggested that this
was the intent for C99, but I'm not convinced -- but perhaps the
authors of gcc were convinced.
Arrays in C are almost always treated as second-class objects. It's
almost impossible to obtain an expression of array type that doesn't
refer to an array object. I believe this can *only* occur when the
array is a member of a struct or union, and that struct or union is
returned from a function -- which is itself the only way (I think) to
obtain an expression of struct or union type that doesn't refer to an
object of struct or union type.
Whether accidentally or deliberately, you've run into an obscure
corner of the language where even the experts don't necessarily agree
on what's supposed to happen. Your best bet, if you're actually
trying to get some work done, is to avoid the issue and use an
explicit temporary.