S
S.Tobias
Netocrat said:The C89 draft says:
"The unary * operator denotes indirection. If the operand points to ... an
object, the result is an lvalue designating the object... If an invalid
value has been assigned to the pointer, the behavior of the unary *
operator is undefined."
Since in this case the pointer has an invalid value it would be illegal to
dereference it; the question of whether or not the result would be an
lvalue is moot.
It is not moot. Being an [rl]value is a compile-time property, and
must be known before the program is run. A compiler must accept
this:
int *p = 0;
/*...*/
*p = 7;
(unless it can prove `p' will always be null ptr). Whatever value
`p' has, `*p' is always an lvalue. If we couldn't make this
statement then the *constraint* that the left operand of "="
be a (modifiable) lvalue would be undiagnosable (IOW every
implementation would be non-conforming... well... unless it
issued any diagnostic each time it were run).
The quote that you have brought in, simply defines the result of
indirection operator; it "explicitly" does not define it when ptr does
not point to an object, in which case it doesn't say if the expression
is an lvalue or not. I think that either mentioning it's an lvalue
in the first case is redundant, or not doing so in the second case
is a flaw. It is difficult to say, because the lvalue definition
in the Standard is seriously flawed anyway.
My "working" definition is: lvalue is an expression that potentially
locates an object. (It might be not strictly correct in a few aspects.)
There're a few useful remarks on lvalues in the Rationale.
Consider also this example:
struct s { int a[1]; };
struct s f(void);
f().a[0] = 7; //UB
The expression on the left is clearly a modifiable lvalue.
This is a minor variation on an example from a previous thread in c.l.c:
struct s {...} s1, s2;
(s1 = s2).a[0] = 7; //UB
Not so clearly according to gcc. I get:
"ISO C90 forbids subscripting non-lvalue array".
gcc is lying. The expression "f().a[0]" is perfectly valid.
It doesn't occur in the context of variable storage in either draft.
If f() were a modifiable lvalue which in this context it does not appear
to be, then I would see nothing wrong with your reasoning.
It doesn't have to be.
int a[1];
a[0];
`a' is not a modifiable lvalue, `a[0]' is (cf. Rationale).
However given
that there's no means of later reading back the assignment, it's really a
no-op and again the question is moot: nothing changes whether the
assignment occurs or not. Perhaps that's why C99 allows it.
I don't quite understand what you mean here. I have written the assignment
to illustrate that `f().a[0]' is an lvalue (a compiler must accept it).
The UB is invoked neither by this expression, nor the assignment itself;
what invokes it is an attempt to modify the return of a function,
cf. 6.5.2.2#5 (hence by the assignment too, but rather indirectly).
Anyway, as to the storage of temporaries in C, I'm going to start
a separate thread on the issue later today.