Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #53806 > unrolled thread

Re: "lvalue"

Started bybuja <buja66@gmail.com>
First post2014-12-03 18:34 +0100
Last post2014-12-05 09:16 -0800
Articles 14 — 6 participants

Back to article view | Back to comp.lang.c

This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by below is the oldest one visible, not the original post.


Contents

  Re: "lvalue" buja <buja66@gmail.com> - 2014-12-03 18:34 +0100
    Re: "lvalue" James Kuyper <jameskuyper@verizon.net> - 2014-12-03 13:03 -0500
    Re: "lvalue" jacob navia <jacob@spamsink.net> - 2014-12-03 19:29 +0100
      Re: "lvalue" buja <buja66@gmail.com> - 2014-12-03 20:01 +0100
        Re: "lvalue" Keith Thompson <kst-u@mib.org> - 2014-12-03 12:18 -0800
        Re: "lvalue" Geoff <geoff@invalid.invalid> - 2014-12-03 12:20 -0800
        Re: "lvalue" James Kuyper <jameskuyper@verizon.net> - 2014-12-03 15:29 -0500
          Re: "lvalue" James Kuyper <jameskuyper@verizon.net> - 2014-12-03 21:48 -0500
            Re: "lvalue" Keith Thompson <kst-u@mib.org> - 2014-12-04 08:20 -0800
              Re: "lvalue" James Kuyper <jameskuyper@verizon.net> - 2014-12-04 11:44 -0500
                Re: "lvalue" Keith Thompson <kst-u@mib.org> - 2014-12-04 11:41 -0800
                  Re: "lvalue" James Kuyper <jameskuyper@verizon.net> - 2014-12-04 14:50 -0500
          Re: "lvalue" Keith Thompson <kst-u@mib.org> - 2014-12-03 23:40 -0800
      Re: "lvalue" Tim Rentsch <txr@alumni.caltech.edu> - 2014-12-05 09:16 -0800

#53806 — Re: "lvalue"

Frombuja <buja66@gmail.com>
Date2014-12-03 18:34 +0100
SubjectRe: "lvalue"
Message-ID<m5nhhr$qda$1@dont-email.me>
On 12/03/2014 10:41 AM, Stefan Ram wrote:
>    N1256 said:
>
>        »An lvalue is an expression with an object type
>        or an incomplete type other than void«.
>
>    That makes »2« an lvalue.
>
>    N1570 says:
>
>        »An lvalue is an expression (with an object type other
>        than void) that potentially designates an object«.
>
>    This now defers the meaning to »potentially designate«,
>    »potentially designate« seems to be vague (not defined).
>
>    And why call an expression a value (an lvalue) at all?
>    After all, an expression is not a value.
>
>    Possibly, it might be better to abandon the term »lvalue«
>    and use »object expression« instead?
>
>    N1570 has changed the wording of N1256 and thereby has
>    acknowledged problems with the wording. N1256 was published
>    in 2007 IIRC. The term »lvalue« was used for decades in
>    the 20th century, and now, in the 21st century, people
>    have problems even saying what it means?
>
K&R (2nd Edition, section A5) says: "An object is a named region of 
storage; an lvalue is an expression referring to an object."

With these definitions, it is clear to me that »2« cannot be an lvalue.

[toc] | [next] | [standalone]


#53808

FromJames Kuyper <jameskuyper@verizon.net>
Date2014-12-03 13:03 -0500
Message-ID<547F507C.8090002@verizon.net>
In reply to#53806
On 12/03/2014 12:34 PM, buja wrote:
> On 12/03/2014 10:41 AM, Stefan Ram wrote:
>>    N1256 said:
>>
>>        »An lvalue is an expression with an object type
>>        or an incomplete type other than void«.
>>
>>    That makes »2« an lvalue.
>>
>>    N1570 says:
>>
>>        »An lvalue is an expression (with an object type other
>>        than void) that potentially designates an object«.
>>
>>    This now defers the meaning to »potentially designate«,
>>    »potentially designate« seems to be vague (not defined).
>>
>>    And why call an expression a value (an lvalue) at all?
>>    After all, an expression is not a value.
>>
>>    Possibly, it might be better to abandon the term »lvalue«
>>    and use »object expression« instead?
>>
>>    N1570 has changed the wording of N1256 and thereby has
>>    acknowledged problems with the wording. N1256 was published
>>    in 2007 IIRC. The term »lvalue« was used for decades in
>>    the 20th century, and now, in the 21st century, people
>>    have problems even saying what it means?
>>
> K&R (2nd Edition, section A5) says: "An object is a named region of 
> storage; an lvalue is an expression referring to an object."
> 
> With these definitions, it is clear to me that »2« cannot be an lvalue.

K&R was, originally, the most authoritative source of information about
C. However, when C was standardized, the C standard became the relevant
authority, and it's the C standard that he's quoting above. K&R 2nd
edition described C90, but any discrepancy between the C90 standard and
K&R 2nd Edition must be resolved in favor of the standard. The above
description is a good match to the C90 wording, so is not evidence of
such a discrepancy.
N1570, cited above, corrects the C90 description to include expressions
that might or might not designate an object, depending upon the values
of their sub-expressions.

[toc] | [prev] | [next] | [standalone]


#53810

Fromjacob navia <jacob@spamsink.net>
Date2014-12-03 19:29 +0100
Message-ID<m5nkqb$6qk$1@speranza.aioe.org>
In reply to#53806
Le 03/12/2014 18:34, buja a écrit :
> "An object is a named region of storage; an lvalue is an expression
> referring to an object."

What a wonderful sentence. Simple, it explains everything.

int table[100];

table[487] = 42;

"table[487]” is a lvalue expression. The fact that the object this 
expression refers to doesn't exist, is a consequence of an error in the 
calculation of the address of the object in the context of the previous 
definition in scope.

This means that it is not necessary to exclude lvalue expressions that 
do not name an actual object since that is the consequence of other 
rules that apply to objects. The "potentially" in the standard is 
unnecessary.

Anyway compilers WILL compile that expression to acces a non existent 
object. Maybe they will emit a warning but that is all. The expression 
is a valid lvalue. The fact that the object doesn't exist will provoke 
consequences that the programmer should be aware of, but the expression 
as such is OK.

The introdution of an undefined concept of "potentially designate" 
complexifies the standard without good reason.

Rule 1:

Scope. In this case the scope of the name is active.

Rule 2: A region is defined by its boundaries, i.e. in a linear memory 
organization there is a start address and an end address where the bits 
in that region are organized in sequences of signed integers of

sizeof(int)*CHAR_BIT

bits. The boundaries specified in the declaration imply the bondaries 
are given by the equation

Stop address is: 100 * sizeof(int)*CHAR_BIT bits.

Lvalues appear in the context of an assignment, where bits from other 
regions are stored in a receiving region. Any miscalculations here are 
fatal and the programmer is supposed to build his/her system by avoiding 
accessing memory out of bounds. This is NOT part of the language.

The ultimate objective of the program can't be expressed in C anyway. C 
can only code the machine operations needed to realize the program. If 
it is a good idea to produce the nth hp calculator simulation for msdos 
in text mode, etc, is not part of the C program and C has no concept or 
guidelines on how to use your time, or if your girlfriend will quit you 
for passing hours coding hp simulators for your old antiquity.

C can speak about machine operations, may they be sinful or errors. 
There is no way that C can understand errors, C speaks about machine 
operations only.

[toc] | [prev] | [next] | [standalone]


#53811

Frombuja <buja66@gmail.com>
Date2014-12-03 20:01 +0100
Message-ID<m5nml1$gho$1@dont-email.me>
In reply to#53810
On 12/03/2014 07:29 PM, jacob navia wrote:
> Le 03/12/2014 18:34, buja a écrit :
>> "An object is a named region of storage; an lvalue is an expression
>> referring to an object."
>
> What a wonderful sentence. Simple, it explains everything.
>

My point exactly.
I know that K&R is not the current standard, but its description is just 
so much clearer than what the current standard has to say about this 
subject.
And I am sure both K&R and the current standard intend to say exactly 
the same thing.

[toc] | [prev] | [next] | [standalone]


#53814

FromKeith Thompson <kst-u@mib.org>
Date2014-12-03 12:18 -0800
Message-ID<lnvblspjwa.fsf@nuthaus.mib.org>
In reply to#53811
buja <buja66@gmail.com> writes:
> On 12/03/2014 07:29 PM, jacob navia wrote:
>> Le 03/12/2014 18:34, buja a écrit :
>>> "An object is a named region of storage; an lvalue is an expression
>>> referring to an object."
>>
>> What a wonderful sentence. Simple, it explains everything.
>
> My point exactly.
> I know that K&R is not the current standard, but its description is just 
> so much clearer than what the current standard has to say about this 
> subject.
> And I am sure both K&R and the current standard intend to say exactly 
> the same thing.

The problem with that simple sentence is that, if taken literally,
it implies that given this:

    int *ptr = NULL;

the expression `*ptr` is not an lvalue, because it doesn't refer to
any object.  You can argue that it obviously *means* that `*ptr` is
an lvalue only if you already have a good idea of what an lvalue is.
The addition of the word "potentially" in C11 fixed that problem,
by making it clear that `*ptr` is unconditionally an lvalue (a
compile-time concept) whether it happens to designate an object at
any particular moment during execution or not.

I don't suggest that the *intent* was ever unclear, or that any
compiler writer would have written code to determine at run time
whether `*ptr` is an lvalue or not.  (I vaguely remember someone
being genuinely confused, thinking that lvalueness must actually
be determined at execution time; I don't remember the details.)
The problem is that the 1990 and 1999 standards did not correctly
express that intent.  The 2011 standard isn't perfect (I'd be
happier with some explanation of what "potentially" means), but
it's closer than either of its predecessors.

Incidentally, an object needn't be named.  A successful call to
malloc creates an anonymous object.  The initial element of an array
can be referred to as `arr[0]`; is that a "name"?  The definition of
"object" in the standard:

    region of data storage in the execution environment, the contents
    of which can represent values

is wordier, but frankly it needs to be.

The standard *needs* to use complex wording to define complex
concepts.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


#53815

FromGeoff <geoff@invalid.invalid>
Date2014-12-03 12:20 -0800
Message-ID<qvru7at8o18cciagjjgl88gco8o4495m8f@4ax.com>
In reply to#53811
On Wed, 03 Dec 2014 20:01:05 +0100, buja <buja66@gmail.com> wrote:

>On 12/03/2014 07:29 PM, jacob navia wrote:
>> Le 03/12/2014 18:34, buja a écrit :
>>> "An object is a named region of storage; an lvalue is an expression
>>> referring to an object."
>>
>> What a wonderful sentence. Simple, it explains everything.
>>
>
>My point exactly.
>I know that K&R is not the current standard, but its description is just 
>so much clearer than what the current standard has to say about this 
>subject.
>And I am sure both K&R and the current standard intend to say exactly 
>the same thing.

In that case it should be:
(Taking K&R and N1570 together.)

"An object is a named region of storage; an lvalue is an expression
referring to an object." "If an lvalue does not designate an object
when it is evaluated, the behavior is undefined."

[toc] | [prev] | [next] | [standalone]


#53816

FromJames Kuyper <jameskuyper@verizon.net>
Date2014-12-03 15:29 -0500
Message-ID<547F72A6.8030502@verizon.net>
In reply to#53811
On 12/03/2014 02:01 PM, buja wrote:
> On 12/03/2014 07:29 PM, jacob navia wrote:
>> Le 03/12/2014 18:34, buja a écrit :
>>> "An object is a named region of storage; an lvalue is an expression
>>> referring to an object."
>>
>> What a wonderful sentence. Simple, it explains everything.
>>
> 
> My point exactly.
> I know that K&R is not the current standard, but its description is just 
> so much clearer than what the current standard has to say about this 
> subject.
> And I am sure both K&R and the current standard intend to say exactly 
> the same thing.

Those two statements cannot both be true. The current standard is
intended to identify *p as an lvalue, even if p has a null or
indeterminate value, in which case *p does NOT refer to an object. C90's
wording agrees with K&R's, and neither one clearly identifies *p as an
lvalue when p is null or indeterminate.
Therefore, either the intent was not the same, or the old wording fails
to clearly specify that intent. Which option do you favor?

[toc] | [prev] | [next] | [standalone]


#53841

FromJames Kuyper <jameskuyper@verizon.net>
Date2014-12-03 21:48 -0500
Message-ID<m5oi1f$jmq$1@dont-email.me>
In reply to#53816
On 12/03/2014 07:38 PM, Stefan Ram wrote:
> James Kuyper <jameskuyper@verizon.net> writes:
>> Those two statements cannot both be true. The current standard is
>> intended to identify *p as an lvalue, even if p has a null or
>> indeterminate value, in which case *p does NOT refer to an object. C90's
> 
>   An attempt by me:
> 
>       �An expression is an /lvalue expression/,
>       if it has the form
> 
>         v,
> 
>       where v is a variable or a parameter,

It would be more consistent with the way the rest of the standard is
written to say that "v is identifier that has been declared as
designating an object" (compare with 6.5.1p2). That covers both of those
cases.

>       or if it has the form
> 
>         *E,
> 
>       where E is an expression of pointer type

You need to be more specific - it should be a pointer to an object type,
and it must point at an actual object (6.5.3.2p4)

>       (or an equivalent expression written with
>       the [] operator)�

The following are also lvalues:

"string literal"                                 (6.5.1p4)
(lvalue)                                         (6.5.1p5)
_Generic(assignment_expression, typename:lvalue) (6.5.1.1p4)
lvalue.member                                    (6.5.2.3p3)
struct_ptr->member                               (6.5.2.3p4)
(type-name){initializer-list}                    (6.5.2.5p4)

The generic definition of "lvalue" that appears in 6.3.2.1p1 is intended
to provide an overview, explaining what all of the specific cases listed
above have in common. If you replace that definition with a list of all
of the specific types of lvalues, that list would be redundant with the
specific clauses cited above, each of which already says that those
things are lvalues.
-- 
James Kuyper

[toc] | [prev] | [next] | [standalone]


#53891

FromKeith Thompson <kst-u@mib.org>
Date2014-12-04 08:20 -0800
Message-ID<lniohrpetm.fsf@nuthaus.mib.org>
In reply to#53841
James Kuyper <jameskuyper@verizon.net> writes:
> On 12/03/2014 07:38 PM, Stefan Ram wrote:
>> James Kuyper <jameskuyper@verizon.net> writes:
>>> Those two statements cannot both be true. The current standard is
>>> intended to identify *p as an lvalue, even if p has a null or
>>> indeterminate value, in which case *p does NOT refer to an object. C90's
>> 
>>   An attempt by me:
>> 
>>       �An expression is an /lvalue expression/,
>>       if it has the form
>> 
>>         v,
>> 
>>       where v is a variable or a parameter,
>
> It would be more consistent with the way the rest of the standard is
> written to say that "v is identifier that has been declared as
> designating an object" (compare with 6.5.1p2). That covers both of those
> cases.
>
>>       or if it has the form
>> 
>>         *E,
>> 
>>       where E is an expression of pointer type
>
> You need to be more specific - it should be a pointer to an object type,
> and it must point at an actual object (6.5.3.2p4)

What do you mean by "it must point to an actual object"?  If E is of
type int*, for example, then *E is an lvalue even if E is a null
pointer.  Actually that last part mixes source code and execution time
concepts.

[...]

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


#53893

FromJames Kuyper <jameskuyper@verizon.net>
Date2014-12-04 11:44 -0500
Message-ID<54808F73.8040103@verizon.net>
In reply to#53891
On 12/04/2014 11:20 AM, Keith Thompson wrote:
> James Kuyper <jameskuyper@verizon.net> writes:
>> On 12/03/2014 07:38 PM, Stefan Ram wrote:
...
>>>       or if it has the form
>>>
>>>         *E,
>>>
>>>       where E is an expression of pointer type
>>
>> You need to be more specific - it should be a pointer to an object type,
>> and it must point at an actual object (6.5.3.2p4)
> 
> What do you mean by "it must point to an actual object"?  If E is of
> type int*, for example, then *E is an lvalue even if E is a null
> pointer.  Actually that last part mixes source code and execution time
> concepts.


(6.5.3.2p4) "If the operand points ... to an object, the result is an
lvalue designating the object."

If the operand is a pointer expression of type "pointer to object", and
it doesn't point to an object, the expression *E has undefined behavior,
so whether or not the result is an lvalue is irrelevant.

Exception: when *E occurs in the expression &*E, neither the & nor the *
is evaluated, so the behavior would not be undefined. The result is
equivalent to E, except that it is not an lvalue (6.5.3.2p3), even if E
itself is.

[toc] | [prev] | [next] | [standalone]


#53901

FromKeith Thompson <kst-u@mib.org>
Date2014-12-04 11:41 -0800
Message-ID<ln1tofp5h9.fsf@nuthaus.mib.org>
In reply to#53893
James Kuyper <jameskuyper@verizon.net> writes:
> On 12/04/2014 11:20 AM, Keith Thompson wrote:
>> James Kuyper <jameskuyper@verizon.net> writes:
>>> On 12/03/2014 07:38 PM, Stefan Ram wrote:
> ...
>>>>       or if it has the form
>>>>
>>>>         *E,
>>>>
>>>>       where E is an expression of pointer type
>>>
>>> You need to be more specific - it should be a pointer to an object type,
>>> and it must point at an actual object (6.5.3.2p4)
>> 
>> What do you mean by "it must point to an actual object"?  If E is of
>> type int*, for example, then *E is an lvalue even if E is a null
>> pointer.  Actually that last part mixes source code and execution time
>> concepts.
>
>
> (6.5.3.2p4) "If the operand points ... to an object, the result is an
> lvalue designating the object."
>
> If the operand is a pointer expression of type "pointer to object", and
> it doesn't point to an object, the expression *E has undefined behavior,
> so whether or not the result is an lvalue is irrelevant.

In my opinion that's just sloppy wording.

Quoting the whole paragraph (and using underscores to denote italics,
since my *usual notation* would be too confusing here):

    The unary * operator denotes indirection. If the operand points to a
    function, the result is a function designator; if it points to an
    object, the result is an lvalue designating the object. If the
    operand has type "pointer to _type_", the result has type
    "_type_". If an invalid value has been assigned to the pointer, the
    behavior of the unary * operator is undefined.

The wording implies that evaluating the expression yields an lvalue,
which appears to go back to the older (pre-C) meaning of "lvalue", in
which an expression could be "evaluated for its lvalue" (to determine
what object it designates) or "evaluated for its rvalue" (what C simply
calls evaluation).

(Incidentally, I haven't been able to find a reference for that older
meaning of "lvalue".)

In C terms, an expression *is* (or is not) an lvalue; it doesn't yield
an lvalue as its result.

What 6.5.3.2p4 *should* say, IMHO, is something like:

    The unary * operator denotes indirection. If the operand is of
    function pointer type, the resulting expression is a function
    designator; if it is of object pointer type, the resulting
    expression is an lvalue designating the object. If the operand has
    type "pointer to _type_", the result has type _type_". If an invalid
    value has been assigned to the pointer, the behavior of the unary *
    operator is undefined.

Possibly there should be some wording in there about void* and/or
pointers to incomplete types.

The expression *E is an lvalue (if E is of object pointer type)
regardless of the value of E.  The wording in 6.5.3.2p4 does seem to
imply otherwise; I think that's an error in the standard, similar to the
one in the C90 definition of "lvalue", that should have been corrected.

> Exception: when *E occurs in the expression &*E, neither the & nor the *
> is evaluated, so the behavior would not be undefined. The result is
> equivalent to E, except that it is not an lvalue (6.5.3.2p3), even if E
> itself is.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


#53903

FromJames Kuyper <jameskuyper@verizon.net>
Date2014-12-04 14:50 -0500
Message-ID<5480BB11.3040600@verizon.net>
In reply to#53901
On 12/04/2014 02:41 PM, Keith Thompson wrote:
...
> The expression *E is an lvalue (if E is of object pointer type)
> regardless of the value of E.  The wording in 6.5.3.2p4 does seem to
> imply otherwise; I think that's an error in the standard, similar to the
> one in the C90 definition of "lvalue", that should have been corrected.

That makes sense to me.

[toc] | [prev] | [next] | [standalone]


#53846

FromKeith Thompson <kst-u@mib.org>
Date2014-12-03 23:40 -0800
Message-ID<lnmw73q2vi.fsf@nuthaus.mib.org>
In reply to#53816
ram@zedat.fu-berlin.de (Stefan Ram) writes:
> James Kuyper <jameskuyper@verizon.net> writes:
>>Those two statements cannot both be true. The current standard is
>>intended to identify *p as an lvalue, even if p has a null or
>>indeterminate value, in which case *p does NOT refer to an object. C90's
>
>   An attempt by me:
>
>       »An expression is an /lvalue expression/,
>       if it has the form
>
>         v,
>
>       where v is a variable or a parameter,
>       or if it has the form
>
>         *E,
>
>       where E is an expression of pointer type
>       (or an equivalent expression written with
>       the [] operator)«

The standard doesn't define the word "variable".  The word "object"
covers both declared variables and parameters.  An identifier is an
lvalue if and only if it's an object name.

A parenthesized lvalue is an lvalue.

*E is an lvalue only if E is of object pointer type; if E is a function
pointer, *E is not an lvalue.

A string literal is an lvalue.

X.Y, where X is an lvalue of struct or union type, is an lvalue.

A compound literal is an lvalue.

And as you said, *E or E1[E2] is an lvalue.

I think that covers it, but I'm not certain.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


#53934

FromTim Rentsch <txr@alumni.caltech.edu>
Date2014-12-05 09:16 -0800
Message-ID<kfnwq66yq35.fsf@x-alumni2.alumni.caltech.edu>
In reply to#53810
jacob navia <jacob@spamsink.net> writes:

> Le 03/12/2014 18:34, buja a  <<E9>> crit :
>> "An object is a named region of storage; an lvalue is an
>> expression referring to an object."
>
> What a wonderful sentence.  Simple, it explains everything.

As explanations go, it's fine.  As a definition to be used in the
Standard, it doesn't work, because it doesn't match how the
Standard uses the term.  In particular, being an lvalue is a
compile-time property, not a run-time property.  The term might
have been defined, eg, "An expression having one of particular
selected syntactic forms, which have the capacity to designate
an object."  It is the form of expression having the capcity to
designate an object that makes the expression an lvalue (as the
Standard uses the term), not what might or not be true when the
program is run.  Even expressions that are never evaluated, eg,
in a sizeof, can be lvalues.

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.c


csiph-web