Tim Rentsch said:
Keith Thompson said:
The phrase "the array object" implies that there must be an array
object somewhere. In the case we're considering (the return value of
a function that returns a struct with an array member), there is no
array object whose initial element we can point to. Is there other
(normative) wording that clarifies this?
Yes, in N1336.
In C90, the section you quoted said that only lvalues with array type
are converted to pointers; C99 relaxed that to allow all array type
expressions to be converted. As you note, that leads to a bit of
cognitive dissonance since an object suddenly appears in the midst of a
value, which doesn't otherwise happen. Nonetheless, you can safely
assume that it's magically created out of the luminiferous aether as
required and mysteriously evaporates again at the next sequence point.
The committee was loathe to say anything more about such objects since
it opens a can of worms (e.g., what storage duration and lifetime they
have), but we bit the bullet for C1X.
[... C90 stuff ...]
I decline to believe that the phrase "the array object" in the C99
standard actually causes such an object to be created (or, more
precisely, imposes a requirement on implementers to arrange for such
an object to be created). In particular, I see no implied guarantee
that "the array object" will continue to exist until the next sequence
point. If the called function returns the value of an object of
struct type, then "the array object" could plausibly refer to the
array member of that object, which could be local to the function and
therefore nonexistent after the function returns.
An object is just a region of memory that can hold values.
The value returned by a function must be held somewhere;
since where ever that is can hold a value, it is an object.
The only question, as you point out, is what its lifetime is.
One interpretation (only slightly perverse) is that in C99
(and probably C90 as well) the lifetime for such an object
must be either static or automatic. (I don't mean to make
the argument, since it's not really a strong argument, but
I think it's worth noting.) The point of the language in
N1336 is not that the result is an object (because it already
must be), but to clarify what the lifetimes of such objects
are.
I disagree.
C, or at least the C abstract machine, distinguishes strongly between
objects and values. An object may hold a value, but a value does not
necessarily require an object to hold it.
A value is the result of evaluating an expresssion. Given, for
example:
int y = 2 * x + 1;
the expression "2 * x" and "2 * x + 1" have values, but those values
don't have objects associated with them. (They might be stored in
memory, but that's an implementation detail.)
And in the following:
int func(void) { return 41; }
...
int x = func() + 1;
there is no object whose value is 41. A function result is just
another expression value. The value specified in a function's return
statement must be communicated somehow to the caller, so that it can
become the result of the function call expression, but again, there's
no implied object. Whether the value happens to be a simple scalar or
some huge structure makes no conceptual difference -- in most cases.
And it wouldn't make any difference in the case under discussion
(accessing an array member of struct value returned from a function)
except for C's (rather odd) rule that an expression of array type is
usually converted to a pointer value. (Note that this isn't a
conversion in the usual sense; an array value consists of the values
of the array elements, and there's no way to get a pointer value from
that other than my compiler magic.)
But since an attempt to refer to an array value implies, because of
The Rule, the existence of an array object, there has to be an object
in this one bizarre case.