cond. op. on ='s LHS

Michael Henning michi at ptcburp.ptcbu.oz.au
Thu Feb 21 10:21:17 AEST 1991


torek at elf.ee.lbl.gov (Chris Torek) writes:

>>throopw at sheol.UUCP (Wayne Throop) writes:
>[the result of unary `*' (indirect) is always an lvalue]

>In article <335 at ptcburp.ptcbu.oz.au> michi at ptcburp.ptcbu.oz.au
>(Michael Henning) writes [abbreviated]:
>>	int	array[10][10];
>>	*array
>>The type of the expression after dereferencing is "array of 10 ints", which
>>is *not* an lvalue.

>Technically, the result *is* an lvalue (according to ANSI terminology,
>at least)---but it is not a `modifiable' lvalue.

>(The type of `array' above is `array 10 of array 10 of int'; in a value
>context, such as the target of unary `*', this changes to `pointer to
>array 10 of int'.  The indirection changes this it `array 10 of int',
>which, in an expression context, devolves to `pointer to int'.  Until
>the final devolving, however, the object produced by the indirection is
>a non-modifiable lvalue of type `array 10 of int'.)

Hmmm..., I'm confused now. From K & R:

"An *object* is a manipulatable region of storage; an *lvalue* is an expression
referring to an object.  [...]  There are operators which yield lvalues:
for example, if E is an expression of pointer type, then *E is an lvalue
expression referring to the object to which E points. The name "lvalue"
comes from the assignment expression E1 = E2 in which the left operand E1
must be an lvalue expression."

And further on, in the section about the * operator:

"The unary * operator means indirection: the expression must be a pointer,
and the result is an lvalue referring to the object to which the expression
points. If the type of the expression is "pointer to ...", the type of the
result is "..."."

And in the section about the various assignment operators:

"  [...]  All require an lvalue as their left operand, and the type of an
assignment expression is that of its left operand.  [...]  "


>From Harbison & Steele:

"An "lvalue" is an expression that refers to an object in such a way that the
object may be altered as well as examined.  [...]  (An expression or result is
called an lvalue because it may be used on the left-hand side of an
assignment.  [...]  )

  [...]

An indirection expression *e is always an lvalue, regardless of whether e
is an lvalue."


Neither K & R nor Harbison & Steele make any distinction between modifiable
and non-modifiable lvalues. Furthermore, both say that the result of
applying a dereference operator to a pointer *always* yields an lvalue,
and that the left operand of an assignment operator must be an lvalue.
Yet, if "array" is a two dimensional array, then "*array", by definition, is
an lvalue, but "*array" cannot appear on the left hand side of an assignment
statement, since the usual unary conversions (conversion to a pointer in this
case) do not take place for the left operand, and the type of the left
operand is "array of 10 ints".

I get the impression that there simply are some inconsistencies in the
language definition. Either an object is an lvalue, in which case it can
be used as the left operand of an assignment, or it isn't, in which case
it cannot be used that way. I believe that the issue could be cleaned up
by changing the definition of "*" to say something like

The unary operator means indirection: the expression must be a pointer, and
the result is an lvalue referring to the object to which the expression points,
except if the object is an array.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Something to that effect should clean things up. Any comments anyone ?

							Michi.
-- 
      -m------- Michael Henning			+61 75 950255
    ---mmm----- Pyramid Technology		+61 75 522475 FAX
  -----mmmmm--- Research Park, Bond University	michi at ptcburp.ptcbu.oz.au
-------mmmmmmm- Gold Coast, Q 4229, AUSTRALIA	uunet!munnari!ptcburp.oz!michi



More information about the Comp.lang.c mailing list