lvalues and rvalues

Discussion in 'C Programming' started by Nicklas Karlsson, Apr 6, 2010.

  1. Hello,

    I am quite confused about this, so I split it in to subquestions, here
    we go:

    1. Is an lvalue the expression itself, or is it the result yielded by
    evaluation of an expression? Take this for example: int i = 10; int *p
    = &i; and then dereference: *p; is the expression "*p" the thing you
    call an lvalue or is an lvalue the result yielded by evaluating that
    lvalue-expression?

    2. Rvalues, is rvalues the result yielded by an rvalue-expression, or
    is it the expression itself? If its the result yielded by evaluation
    of an rvalue-expression is an rvalue a plain value?

    3. I am quite sure that in a conversion from C to Assembly an lvalue-
    expression yields an an address when evaluated, however, in C an
    lvalue seems to have properties, an address and a type, again, using
    the example of *p, the lvalue will be of type "int", if an lvalue-
    expression always yields an address when evaluated, C could keep track
    of the addresses type, so if the lvalue (the address) is "0x0" and C
    knows the addresses type is "int*" does C everytime it encounters that
    lvalue say "here you can only read/write an int because the address is
    int*" and therefor the type of the lvalue is "int"? But if its just an
    address how can it have a type other then the addresses type? That
    makes me wonder what an lvalue acctually is in C, how should I think
    about it? It's something that keeps track of an address and type?

    Kind regards // Nicklas
     
    Nicklas Karlsson, Apr 6, 2010
    #1
    1. Advertising

  2. Nicklas Karlsson

    John Bode Guest

    On Apr 6, 2:37 pm, Nicklas Karlsson <>
    wrote:
    > Hello,
    >
    > I am quite confused about this, so I split it in to subquestions, here
    > we go:
    >
    > 1. Is an lvalue the expression itself, or is it the result yielded by
    > evaluation of an expression? Take this for example: int i = 10; int *p
    > = &i; and then dereference: *p; is the expression "*p" the thing you
    > call an lvalue or is an lvalue the result yielded by evaluating that
    > lvalue-expression?
    >


    The expression is the lvalue (quoting H&S: "An lvalue is an expression
    that refers to an object in such a way that the object may be examined
    or altered."). So i, p, and *p are all lvalues, while &i and 10 are
    not.

    > 2. Rvalues, is rvalues the result yielded by an rvalue-expression, or
    > is it the expression itself? If its the result yielded by evaluation
    > of an rvalue-expression is an rvalue a plain value?


    Again, it refers to the expression. Any expression that cannot be an
    lvalue is an rvalue.

    >
    > 3. I am quite sure that in a conversion from C to Assembly an lvalue-
    > expression yields an an address when evaluated, however, in C an
    > lvalue seems to have properties, an address and a type, again, using
    > the example of *p, the lvalue will be of type "int", if an lvalue-
    > expression always yields an address when evaluated, C could keep track
    > of the addresses type, so if the lvalue (the address) is "0x0" and C
    > knows the addresses type is "int*" does C everytime it encounters that
    > lvalue say "here you can only read/write an int because the address is
    > int*" and therefor the type of the lvalue is "int"? But if its just an
    > address how can it have a type other then the addresses type? That
    > makes me wonder what an lvalue acctually is in C, how should I think
    > about it? It's something that keeps track of an address and type?
    >
    > Kind regards // Nicklas


    You're overthinking things a bit. The distinction between lvalues and
    rvalues has mostly to do with what legally may be the target of an
    assignment; type is a separate issue.

    For example, if the type of x is long, then the type of x++ is also
    long, but x++ is not an lvalue.
     
    John Bode, Apr 6, 2010
    #2
    1. Advertising

  3. Nicklas Karlsson <> writes:
    > I am quite confused about this, so I split it in to subquestions, here
    > we go:


    Yes, it's confusing. The C standard's definitions of "lvalue" and
    "rvalue" aren't necessarily consistent with their historical usage.

    > 1. Is an lvalue the expression itself, or is it the result yielded by
    > evaluation of an expression? Take this for example: int i = 10; int *p
    > = &i; and then dereference: *p; is the expression "*p" the thing you
    > call an lvalue or is an lvalue the result yielded by evaluating that
    > lvalue-expression?


    An "lvalue" is, roughly, an expression that designates an object.
    (The C90 and C99 standard both managed to get the definition
    seriously wrong, but that's the gist of it.)

    > 2. Rvalues, is rvalues the result yielded by an rvalue-expression, or
    > is it the expression itself? If its the result yielded by evaluation
    > of an rvalue-expression is an rvalue a plain value?


    A footnote in the standard says

    What is sometimes called ‘‘rvalue’’ is in this International
    Standard described as the ‘‘value of an expression’’.

    So an lvalue is a kind of expression, and an rvalue is the
    value that results from evaluating an expression.

    > 3. I am quite sure that in a conversion from C to Assembly an lvalue-
    > expression yields an an address when evaluated, however, in C an
    > lvalue seems to have properties, an address and a type, again, using
    > the example of *p, the lvalue will be of type "int", if an lvalue-
    > expression always yields an address when evaluated, C could keep track
    > of the addresses type, so if the lvalue (the address) is "0x0" and C
    > knows the addresses type is "int*" does C everytime it encounters that
    > lvalue say "here you can only read/write an int because the address is
    > int*" and therefor the type of the lvalue is "int"? But if its just an
    > address how can it have a type other then the addresses type? That
    > makes me wonder what an lvalue acctually is in C, how should I think
    > about it? It's something that keeps track of an address and type?


    An lvalue is not an address, though it's a related concept. An lvalue
    doesn't point to an object, it "designates" an object.

    For example, given

    int x;

    the expression ``x'' is an lvalue. It refers to the object x, not to
    the address of that object (that would be ``&x'', which is *not* an
    lvalue).

    Whether an expression is an lvalue or not is relevant only in some
    contexts, namely those contexts that require an lvalue. The most
    obvious example is the left side of an assignment. For example:

    x = 42;

    is valid, because x is an value, but

    41 = 42;

    is not, because 41 is not an lvalue. The right hand side needn't be
    an lvalue; only the *value* of the RHS is needed. But the left hand
    side must designate an object

    <http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf> is the
    latest post-C99 draft; it includes the material from the C99 standard
    plus the three Technical Corrigenda. Section 6.3.2.1 discusses
    lvalues. Be aware that the definition of the term in the first
    paragraph is flawed, but it's otherwise a good explanation.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Nokia
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, Apr 6, 2010
    #3
  4. On Apr 6, 9:59 pm, Keith Thompson <> wrote:
    > Nicklas Karlsson <> writes:
    > > I am quite confused about this, so I split it in to subquestions, here
    > > we go:

    >
    > Yes, it's confusing.  The C standard's definitions of "lvalue" and
    > "rvalue" aren't necessarily consistent with their historical usage.
    >
    > > 1. Is an lvalue the expression itself, or is it the result yielded by
    > > evaluation of an expression? Take this for example: int i = 10; int *p
    > > = &i; and then dereference: *p; is the expression "*p" the thing you
    > > call an lvalue or is an lvalue the result yielded by evaluating that
    > > lvalue-expression?

    >
    > An "lvalue" is, roughly, an expression that designates an object.
    > (The C90 and C99 standard both managed to get the definition
    > seriously wrong, but that's the gist of it.)
    >
    > > 2. Rvalues, is rvalues the result yielded by an rvalue-expression, or
    > > is it the expression itself? If its the result yielded by evaluation
    > > of an rvalue-expression is an rvalue a plain value?

    >
    > A footnote in the standard says
    >
    >     What is sometimes called ‘‘rvalue’’ is in this International
    >     Standard described as the ‘‘value of an expression’’.
    >
    > So an lvalue is a kind of expression, and an rvalue is the
    > value that results from evaluating an expression.
    >
    > > 3. I am quite sure that in a conversion from C to Assembly an lvalue-
    > > expression yields an an address when evaluated, however, in C an
    > > lvalue seems to have properties, an address and a type, again, using
    > > the example of *p, the lvalue will be of type "int", if an lvalue-
    > > expression always yields an address when evaluated, C could keep track
    > > of the addresses type, so if the lvalue (the address) is "0x0" and C
    > > knows the addresses type is "int*" does C everytime it encounters that
    > > lvalue say "here you can only read/write an int because the address is
    > > int*" and therefor the type of the lvalue is "int"? But if its just an
    > > address how can it have a type other then the addresses type? That
    > > makes me wonder what an lvalue acctually is in C, how should I think
    > > about it? It's something that keeps track of an address and type?

    >
    > An lvalue is not an address, though it's a related concept.  An lvalue
    > doesn't point to an object, it "designates" an object.
    >
    > For example, given
    >
    >     int x;
    >
    > the expression ``x'' is an lvalue.  It refers to the object x, not to
    > the address of that object (that would be ``&x'', which is *not* an
    > lvalue).
    >
    > Whether an expression is an lvalue or not is relevant only in some
    > contexts, namely those contexts that require an lvalue.  The most
    > obvious example is the left side of an assignment.  For example:
    >
    >     x = 42;
    >
    > is valid, because x is an value, but
    >
    >     41 = 42;
    >
    > is not, because 41 is not an lvalue.  The right hand side needn't be
    > an lvalue; only the *value* of the RHS is needed.  But the left hand
    > side must designate an object
    >
    > <http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf> is the
    > latest post-C99 draft; it includes the material from the C99 standard
    > plus the three Technical Corrigenda.  Section 6.3.2.1 discusses
    > lvalues.  Be aware that the definition of the term in the first
    > paragraph is flawed, but it's otherwise a good explanation.
    >
    > --
    > Keith Thompson (The_Other_Keith)  <http://www.ghoti.net/~kst>
    > Nokia
    > "We must do something.  This is something.  Therefore, we must do this."
    >     -- Antony Jay and Jonathan Lynn, "Yes Minister"


    Im not sure I follow, an rvalue is the value of an expression, its not
    an expression? While an lvalue is an expression? But an lvalue is an
    expression that does not evaluate to an rvalue? And since an lvalue is
    an expression it evaluates to something, what exactly does it evaluate
    to? Something that has a designated object and has a type? I read that
    PDF and it said: "if an lvalue does not designate an object when it is
    evaluated..." so it is something that designates an object? Am I
    thinking wrong? And the expression does evaluate to an address? I read
    this: http://accu.org/index.php/journals/227 it sorta says "every
    expression yields either an lvalue or an rvalue and accordingly every
    expression is called either an lvalue or an rvalue expression." that
    is wrong, well it appears to be right now anyhow?
     
    Nicklas Karlsson, Apr 6, 2010
    #4
  5. On Tue, 06 Apr 2010 15:59:01 -0400, Keith Thompson <> wrote:

    > int x;

    ....
    > Whether an expression is an lvalue or not is relevant only in some
    > contexts, namely those contexts that require an lvalue. The most
    > obvious example is the left side of an assignment. For example:
    > x = 42;
    > is valid, because x is an value


    [obviously a slip of the keyboard, and intended to read "x is an lvalue"].

    The other obvious example of a context that requires an lvalue is the
    operand of the unary & operator. An lvalue is something that has an
    address, so

    &x

    is a valid expression, while

    &42

    is not. Given

    const int y = 42;

    y is an lvalue, so &y is a valid expression, while &42 is not, even though
    y cannot appear on the left side of an assignment operator (because it's
    an unmodifiable lvalue).


    --
    Morris Keesan --
     
    Morris Keesan, Apr 6, 2010
    #5
  6. Nicklas Karlsson <> writes:
    [...]
    > Im not sure I follow, an rvalue is the value of an expression, its not
    > an expression? While an lvalue is an expression?


    Yes, given the way the C standard defines the terms.

    > But an lvalue is an
    > expression that does not evaluate to an rvalue?


    No.

    Keep in mind that the C standard doesn't generally use the term
    "rvalue". The only two occurences of the term are in that footnote
    and in the corresponding index entry. If you're discussing C, it's
    best to avoid the term "rvalue" altogether.

    If an lvalue (a kind of expression) appears in a context that requires
    an lvalue, it doesn't yield a result in the ordinary sense; rather, it
    serves to designate (or identify) the object that's required in that
    context. If it appears on the LHS of an assignment operator, it
    designates the object to which a value is to be assigned. If it
    appears as the operand of a unary "&" operator, it designates the
    object whose address is taken. And so forth.

    If an lvalue appears in a context that *doesn't* require an lvalue, it
    yields an ordinary value -- specifically, it yields the stored value
    of the object that it designates.

    Thus:

    int x = 10;
    int y = 20;
    x = y;

    In the assignment, both ``x'' and ''y'' are lvalues. Since ``x'' is
    in a context that requires an lvalue, it identifies the object to be
    written to (the previous value of that object, 10, is ignored). Since
    ''y'' is in a context that *doesn't* require an lvalue, it yields the
    value (20) stored in the object that it designates (y).

    (I'm using ``y'' to refer to the expression consisting of the
    identifier y and just y to refer to the object. This isn't a standard
    typographical convention, just the one I'm using here.)

    > And since an lvalue is
    > an expression it evaluates to something, what exactly does it evaluate
    > to?


    It depends on the context; see above.

    > Something that has a designated object and has a type? I read that
    > PDF and it said: "if an lvalue does not designate an object when it is
    > evaluated..." so it is something that designates an object? Am I
    > thinking wrong?


    An lvalue is an expression that designates an object.

    Actually, that's not *quite* accurate. Given:
    int *ptr = NULL;
    the expression *ptr is an lvalue, even though it doesn't happen to
    refer to any object at run time. This is the subtlety that has
    tripped up the authors of the standard in trying to define the term.
    (I won't go into the gory details yet again unless you really want me
    to.)

    What the standard probably should say is "if an lvalue does not
    designate an object when it is evaluated *in a context that requires
    an lvalue*, the behavior is undefined. And the definition should say
    something along the lines that an lvalue is an expression that
    *potentially* designates an object.

    Given:

    int x = 42;
    int *ptr;

    the expressions ``x'' and` ``*ptr'' are both lvalues. ``x''
    unconditionally designates an object. ``*ptr'' may or may not
    designate an object, depending on the value currently stored in
    ptr; this is where the potential for undefined behavior comes in.
    ``42'' cannot possibly designate an object and is not an lvalue,
    so an attempt to use it in a context requiring an lvalue will be
    flagged at compile time.

    > And the expression does evaluate to an address?


    No. Evaluating an lvalue in a context that requires an lvalue
    identifies an object. It doesn't yield the object's address. It
    could well be implemented by computing the object's address, but
    consider this:
    register int reg;
    reg = 42;
    The object reg has no address, but ``reg'' nevertheless designates
    that object. The same applies to bit fields, which also have no
    address.

    > I read
    > this: http://accu.org/index.php/journals/227 it sorta says "every
    > expression yields either an lvalue or an rvalue and accordingly every
    > expression is called either an lvalue or an rvalue expression." that
    > is wrong, well it appears to be right now anyhow?


    It "sorta says"? Actually, you quoted the exact words, but you
    didn't quote the beginning of the sentence:

    *In C++* every expression yields either an lvalue or an rvalue and
    accordingly every expression is called either an lvalue or an
    rvalue expression.

    I think that C++ defines the terms differently than C does. For
    information on C++, see elsewhere.

    I mentioned that the C standard doesn't use the traditional meanings
    of the terms. I'll summarize my understanding of what those
    traditional meanings are.

    In a very simple language without objects, each expression yields a
    value when evaluated. ``2 + 2'' yields the value 4, for example.

    Once you introduce objects, assuming you want to treat assignments as
    expressions, there are two possible ways to evaluate an expression.
    You can either evaluate it to determine its value (``2 + 2'' yields
    4, ``x + 3'' yields 45 if you've previously stored the value 42 in
    x) *or* you can evaluate it to determine what object it designates,
    ignoring any value that might be stored in that object. Which of
    these things happens depends on the context in which the expression
    appears. Traditionally, the former is referred to as "evaluating
    an expression for its rvalue", and the latter as "evaluating an
    expression for its lvalue". An rvalue is just an ordinary value of
    some type. An lvalue is something that, rather than being a *value*
    of some type, identifies an *object* of some type. The traditional
    terminology unifies these two things (having a value vs. identifying
    an object) into the single concept of "value", divided into "rvalue"
    and "lvalue". The names of course come from the contexts in which
    they appear, the right side vs. the left side of an assignment.

    Note that some expressions, such as ``2 + 2'' cannot be evaluated for
    their lvalues. (In C terms, ``2 + 2'' is not an lvalue.)

    The authors of the C standard chose to drop the concept of "rvalue"
    (other than a brief mention in a footnote which matches the
    traditional meaning) and redefine "lvalue" as a kind of expression
    rather than as the result of evaluating such an expression.

    I'm sorry this is so long; I didn't have time to make it shorter.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Nokia
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, Apr 6, 2010
    #6
  7. Nicklas Karlsson

    bartc Guest

    "Nicklas Karlsson" <> wrote in message
    news:...
    > Hello,
    >
    > I am quite confused about this, so I split it in to subquestions, here
    > we go:
    >
    > 1. Is an lvalue the expression itself, or is it the result yielded by
    > evaluation of an expression? Take this for example: int i = 10; int *p
    > = &i; and then dereference: *p; is the expression "*p" the thing you
    > call an lvalue or is an lvalue the result yielded by evaluating that
    > lvalue-expression?


    A rule of thumb might be: if you can apply the & operator to it
    (address-of), then it can be an lvalue (with a few exceptions such as
    function names)

    But here:

    int A,B;

    A = B;

    Both A,B could be lvalues, but only A is being used as one. (In assembly,
    you will find little difference between how the two are treated:

    mov [A], # assuming memory-to-memory allowed

    (I'm done a bit of compiler work; I would handle the assignment above as
    follows:

    *(&A) = B;

    Ie. apply address-of to the left-hand-side, then dereference. The * and &
    cancel out, but it has now verified the left-side is an lvalue. If you try
    and write:

    56 = B;

    this obviously won't work (since &56 is not allowed).)

    >
    > 2. Rvalues, is rvalues the result yielded by an rvalue-expression, or
    > is it the expression itself? If its the result yielded by evaluation
    > of an rvalue-expression is an rvalue a plain value?


    There will be some technical interpretation somewhere or other. To me, the
    rvalue would be the result of evaluating the expression: a value with a
    type. (In some languages, this is not quite so clear-cut; fortunately this
    is C.)

    > 3. I am quite sure that in a conversion from C to Assembly an lvalue-
    > expression yields an an address when evaluated,


    Try looking at some assembly output.

    > however, in C an
    > lvalue seems to have properties, an address and a type, again, using
    > the example of *p, the lvalue will be of type "int", if an lvalue-
    > expression always yields an address when evaluated, C could keep track
    > of the addresses type, so if the lvalue (the address) is "0x0" and C
    > knows the addresses type is "int*" does C everytime it encounters that
    > lvalue say "here you can only read/write an int because the address is
    > int*" and therefor the type of the lvalue is "int"? But if its just an
    > address how can it have a type other then the addresses type? That
    > makes me wonder what an lvalue acctually is in C, how should I think
    > about it? It's something that keeps track of an address and type?


    int A=78;

    Here, several things are happening:

    'A' A is really the name of a location, or address, containing 78.
    Let's say this is address 0x400100.
    The type of 'A' is pointer-to-int. However, C automatically
    dereferences such names (in common with other languages), so:

    A Will dereference the 'A' address with value 0x400100, to fetch
    the value 78. This is now type int.

    &A This overrides the automatic dereference to allow access to the
    address. The value is 0x400100 with type pointer-to-int.

    Which of this is an lvalue? Well A *can* be an lvalue, because you
    can use & on it to obtain it's address (0x400100), allowing you to
    store another value in there:

    A = 79;

    But I don't think an lvalue is specifically the address of something. Here:

    enum {C=12};

    'C' is the name of a constant value '12'. There is no address, and
    therefore it can't be an lvalue. The type I would guess is just int.


    --
    Bartc
     
    bartc, Apr 6, 2010
    #7
  8. On Apr 6, 11:38 pm, Keith Thompson <> wrote:
    > Nicklas Karlsson <> writes:
    >
    > [...]
    >
    > > Im not sure I follow, an rvalue is the value of an expression, its not
    > > an expression? While an lvalue is an expression?

    >
    > Yes, given the way the C standard defines the terms.
    >
    > >                                                  But an lvalue is an
    > > expression that does not evaluate to an rvalue?

    >
    > No.
    >
    > Keep in mind that the C standard doesn't generally use the term
    > "rvalue".  The only two occurences of the term are in that footnote
    > and in the corresponding index entry.  If you're discussing C, it's
    > best to avoid the term "rvalue" altogether.
    >
    > If an lvalue (a kind of expression) appears in a context that requires
    > an lvalue, it doesn't yield a result in the ordinary sense; rather, it
    > serves to designate (or identify) the object that's required in that
    > context.  If it appears on the LHS of an assignment operator, it
    > designates the object to which a value is to be assigned.  If it
    > appears as the operand of a unary "&" operator, it designates the
    > object whose address is taken.  And so forth.
    >
    > If an lvalue appears in a context that *doesn't* require an lvalue, it
    > yields an ordinary value -- specifically, it yields the stored value
    > of the object that it designates.
    >
    > Thus:
    >
    >     int x = 10;
    >     int y = 20;
    >     x = y;
    >
    > In the assignment, both ``x'' and ''y'' are lvalues.  Since ``x'' is
    > in a context that requires an lvalue, it identifies the object to be
    > written to (the previous value of that object, 10, is ignored).  Since
    > ''y'' is in a context that *doesn't* require an lvalue, it yields the
    > value (20) stored in the object that it designates (y).
    >
    > (I'm using ``y'' to refer to the expression consisting of the
    > identifier y and just y to refer to the object.  This isn't a standard
    > typographical convention, just the one I'm using here.)
    >
    > >                                                 And since an lvalue is
    > > an expression it evaluates to something, what exactly does it evaluate
    > > to?

    >
    > It depends on the context; see above.
    >
    > >     Something that has a designated object and has a type? I read that
    > > PDF and it said: "if an lvalue does not designate an object when it is
    > > evaluated..." so it is something that designates an object? Am I
    > > thinking wrong?

    >
    > An lvalue is an expression that designates an object.
    >
    > Actually, that's not *quite* accurate.  Given:
    >     int *ptr = NULL;
    > the expression *ptr is an lvalue, even though it doesn't happen to
    > refer to any object at run time.  This is the subtlety that has
    > tripped up the authors of the standard in trying to define the term.
    > (I won't go into the gory details yet again unless you really want me
    > to.)
    >
    > What the standard probably should say is "if an lvalue does not
    > designate an object when it is evaluated *in a context that requires
    > an lvalue*, the behavior is undefined.  And the definition should say
    > something along the lines that an lvalue is an expression that
    > *potentially* designates an object.
    >
    > Given:
    >
    >     int x = 42;
    >     int *ptr;
    >
    > the expressions ``x'' and` ``*ptr'' are both lvalues.  ``x''
    > unconditionally designates an object.  ``*ptr'' may or may not
    > designate an object, depending on the value currently stored in
    > ptr; this is where the potential for undefined behavior comes in.
    > ``42'' cannot possibly designate an object and is not an lvalue,
    > so an attempt to use it in a context requiring an lvalue will be
    > flagged at compile time.
    >
    > >                 And the expression does evaluate to an address?

    >
    > No.  Evaluating an lvalue in a context that requires an lvalue
    > identifies an object.  It doesn't yield the object's address.  It
    > could well be implemented by computing the object's address, but
    > consider this:
    >     register int reg;
    >     reg = 42;
    > The object reg has no address, but ``reg'' nevertheless designates
    > that object.  The same applies to bit fields, which also have no
    > address.
    >
    > >                                                                 I read
    > > this:http://accu.org/index.php/journals/227it sorta says "every
    > > expression yields either an lvalue or an rvalue and accordingly every
    > > expression is called either an lvalue or an rvalue expression." that
    > > is wrong, well it appears to be right now anyhow?

    >
    > It "sorta says"?  Actually, you quoted the exact words, but you
    > didn't quote the beginning of the sentence:
    >
    >     *In C++* every expression yields either an lvalue or an rvalue and
    >     accordingly every expression is called either an lvalue or an
    >     rvalue expression.
    >
    > I think that C++ defines the terms differently than C does.  For
    > information on C++, see elsewhere.
    >
    > I mentioned that the C standard doesn't use the traditional meanings
    > of the terms.  I'll summarize my understanding of what those
    > traditional meanings are.
    >
    > In a very simple language without objects, each expression yields a
    > value when evaluated.  ``2 + 2'' yields the value 4, for example.
    >
    > Once you introduce objects, assuming you want to treat assignments as
    > expressions, there are two possible ways to evaluate an expression.
    > You can either evaluate it to determine its value (``2 + 2'' yields
    > 4, ``x + 3'' yields 45 if you've previously stored the value 42 in
    > x) *or* you can evaluate it to determine what object it designates,
    > ignoring any value that might be stored in that object.  Which of
    > these things happens depends on the context in which the expression
    > appears.  Traditionally, the former is referred to as "evaluating
    > an expression for its rvalue", and the latter as "evaluating an
    > expression for its lvalue".  An rvalue is just an ordinary value of
    > some type.  An lvalue is something that, rather than being a *value*
    > of some type, identifies an *object* of some type.  The traditional
    > terminology unifies these two things (having a value vs. identifying
    > an object) into the single concept of "value", divided into "rvalue"
    > and "lvalue".  The names of course come from the contexts in which
    > they appear, the right side vs. the left side of an assignment.
    >
    > Note that some expressions, such as ``2 + 2'' cannot be evaluated for
    > their lvalues.  (In C terms, ``2 + 2'' is not an lvalue.)
    >
    > The authors of the C standard chose to drop the concept of "rvalue"
    > (other than a brief mention in a footnote which matches the
    > traditional meaning) and redefine "lvalue" as a kind of expression
    > rather than as the result of evaluating such an expression.
    >
    > I'm sorry this is so long; I didn't have time to make it shorter.
    >
    > --
    > Keith Thompson (The_Other_Keith)  <http://www.ghoti.net/~kst>
    > Nokia
    > "We must do something.  This is something.  Therefore, we must do this."
    >     -- Antony Jay and Jonathan Lynn, "Yes Minister"


    Thanks for the reply guys!

    So an lvalue does NOT evaluate in a traditional sense (yield a value)
    but its being EVALUATED, so that the compiler can identify an object
    and a size, the result of the evaluation specifies an object and a
    type (and an object is a memory address right?) so if its on the left
    side of assignenment it tells the compiler where to put the rvalue and
    how much it can put, and if it appears on the right hand of assignment
    it tells the compiler where to read the rvalue and how much to read?
    Then you confuse me :)P) and say "and the latter as 'evaluating an
    expression for its lvalue'", I thought we establised that the
    expression itself was the lvalue?

    In this: http://publib.boulder.ibm.com/infoc...ibm.vacpp6m.doc/language/ref/clrc05lvalue.htm
    they call rvalues expressions too, but that is faulty (as the C-
    standard says its a value of an expression), it may only apply to C++?
    It also says: "When an lvalue appears in a context that requires an
    rvalue, the lvalue is implicitly converted to an rvalue." that just
    means that it starts to reads the rvalue at the address the lvalue
    identifies? The lvalue is still evaluated right?

    See I dont have a C-bot but a C++-bot and it shows precedence like
    this ((*p) = 5); for *p = 5; and the (*p) must show that its being
    evaluated right? But it shows i = 5; as (i = 5) but both are
    expressions so I dont get why precedence differs?
     
    Nicklas Karlsson, Apr 6, 2010
    #8
  9. Nicklas Karlsson <> writes:
    [...]
    > Thanks for the reply guys!


    When you post a followup, please trim any quoted material that isn't
    necessary. In particular, please don't quote signatures.

    > So an lvalue does NOT evaluate in a traditional sense (yield a value)
    > but its being EVALUATED, so that the compiler can identify an object
    > and a size,


    Yes, but I wouldn't place so much emphasis on the size.

    An lvalue (which is an expression) is of a particular type (and the
    size is an attribute of that type). It identifies an object, which is
    treated as being of that type. Usually that's going to be the
    declared typethe object. If it's not (say, if there are pointer
    conversions involved), then the type of the lvalue is what determines
    the behavior.

    A silly example:

    int n;
    *(unsigned int*)&n = 43;

    Here n is declared to be of type int, but the lvalue
    *(unsigned int*)&n
    is of type unigsned int.

    > the result of the evaluation specifies an object and a
    > type (and an object is a memory address right?)


    An object is, by definition, a "region of data storage in the
    execution environment, the contents of which can represent values"
    (C99 3.14). An object is not an address; an object (usually) *has* an
    address.

    > so if its on the left
    > side of assignenment it tells the compiler where to put the rvalue and
    > how much it can put,


    It tells the compiler the identify and type of the object into which
    the value is to be stored. Remember I suggested avoiding the term
    "rvalue"; the value to be stored is the value resulting from the
    evaluation of the RHS expression.

    > and if it appears on the right hand of assignment
    > it tells the compiler where to read the rvalue and how much to read?


    If an lvalue appears as the RHS of an assignment, it's just evaluated,
    yielding the value stored in the designated object.

    > Then you confuse me :)P) and say "and the latter as 'evaluating an
    > expression for its lvalue'", I thought we establised that the
    > expression itself was the lvalue?


    In C terms, yes. As I said, the C standard assigns a non-traditional
    meaning to the term "lvalue". In C, the expression itself is the
    lvalue.

    > In this: http://publib.boulder.ibm.com/infoc...ibm.vacpp6m.doc/language/ref/clrc05lvalue.htm
    > they call rvalues expressions too, but that is faulty (as the C-
    > standard says its a value of an expression), it may only apply to C++?
    > It also says: "When an lvalue appears in a context that requires an
    > rvalue, the lvalue is implicitly converted to an rvalue." that just
    > means that it starts to reads the rvalue at the address the lvalue
    > identifies? The lvalue is still evaluated right?


    You're asking about C++ in a C newsgroup. lvalue-to-rvalue conversion
    is a C++ concept, not a C concept. C++ has its own set of newsgroups
    (and FAQs, which you should check before posting).

    (I just checked the C++ standard. C++ definitely defines "rvalue"
    differently than C does. Its definition of "lvalue' may or may not
    be consistent with C's.)

    > See I dont have a C-bot but a C++-bot and it shows precedence like
    > this ((*p) = 5); for *p = 5; and the (*p) must show that its being
    > evaluated right? But it shows i = 5; as (i = 5) but both are
    > expressions so I dont get why precedence differs?


    Precedence has nothing to do with it.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Nokia
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, Apr 7, 2010
    #9
  10. > You're asking about C++ in a C newsgroup.  lvalue-to-rvalue conversion
    > is a C++ concept, not a C concept.  C++ has its own set of newsgroups
    > (and FAQs, which you should check before posting).


    Sorry, from the looks of it I thought that link was talking about both
    C and C++


    So if an identifier is declared and used as an lvalue, the compiler
    knows that lvalues type because its the type which the the identifier
    is declared with, and if its pointer conversion the compiler knows the
    lvalues type from context (for example *(int*)0x0 will be an lvalue of
    type "int"), so is it the expression itself that has a type or does
    that expression evaluate so that the compiler knows its type (and
    therefor size), like "this lvalue evaluated, the object it designated
    starts at address ****** and the type of that object is"?

    An object is, and I quote: "a region of data storage in the execution
    environment, the contents of which can represent values" so its an
    entire region of memory (usally), which is usally identified by a
    memory address?

    "If an lvalue appears as the RHS of an assignment, it's just
    evaluated, yielding the value stored in the designated object." so
    there is no conversion going on? it evaluates the lvalue and reads the
    data of the object that lvalue identified?

    "Precedence has nothing to do with it."
    I thought it was order of evaluation, and I'm just wondering why one
    lvalue (indirection) is different from an identifer as an lvalue in
    terms of evaluation, but its probably off topic since its a C++ bot
    and what I linked earlier about C++ lvalues seem different than C's

    "knows what type is going to be used for that object"
     
    Nicklas Karlsson, Apr 7, 2010
    #10
  11. On 06 Apr 2010 16:38, Keith Thompson wrote:
    > Given:
    >
    > int x = 42;
    > int *ptr;
    >
    > the expressions ``x'' and` ``*ptr'' are both lvalues. ``x''
    > unconditionally designates an object. ``*ptr'' may or may not
    > designate an object, depending on the value currently stored in
    > ptr; this is where the potential for undefined behavior comes in.


    "ptr" also unconditionally designates an object. (I'm sure you knew
    that; I just point it out for completeness.)

    > I mentioned that the C standard doesn't use the traditional meanings
    > of the terms. I'll summarize my understanding of what those
    > traditional meanings are.
    > ...
    > An rvalue is just an ordinary value of
    > some type. An lvalue is something that, rather than being a *value*
    > of some type, identifies an *object* of some type. The traditional
    > terminology unifies these two things (having a value vs. identifying
    > an object) into the single concept of "value", divided into "rvalue"
    > and "lvalue". The names of course come from the contexts in which
    > they appear, the right side vs. the left side of an assignment.
    >
    > Note that some expressions, such as ``2 + 2'' cannot be evaluated for
    > their lvalues. (In C terms, ``2 + 2'' is not an lvalue.)
    >
    > The authors of the C standard chose to drop the concept of "rvalue"
    > (other than a brief mention in a footnote which matches the
    > traditional meaning) and redefine "lvalue" as a kind of expression
    > rather than as the result of evaluating such an expression.


    Is dropping the term "rvalue" why the C Standard's definition of
    "lvalue" is so tortuous--and continues to get even more so with each
    revision as they try to correct problems with the prior one?

    Digesting what you have said, this is how I mentally process the terms:

    .. A modifiable lvalue is any expression which _could_ have a meaningful
    result if it appeared on the LHS of an assignment.
    .. A non-modifiable lvalue is any expression which _would_ be a
    modifiable lvalue if it weren't const.
    .. An rvalue is any expression which isn't an lvalue.
    .. If an lvalue occurs in a context which does not require an lvalue, it
    is evaluated to produce an rvalue.

    Granted, that definitely isn't how the C Standard uses or defines the
    terms, but aside from that, is it accurate enough for someone other than
    a compiler author? Or is there some subtle flaw in there that will bite
    me someday?

    S

    --
    Stephen Sprunk "God does not play dice." --Albert Einstein
    CCIE #3723 "God is an inveterate gambler, and He throws the
    K5SSS dice at every possible opportunity." --Stephen Hawking
     
    Stephen Sprunk, Apr 7, 2010
    #11
  12. Stephen Sprunk <> writes:
    [...]
    > Is dropping the term "rvalue" why the C Standard's definition of
    > "lvalue" is so tortuous--and continues to get even more so with each
    > revision as they try to correct problems with the prior one?


    I don't think so. I think the problem is with "lvalue", not with
    "rvalue". I find lvalues to be a more complicated concept anyway, for
    either definition.

    > Digesting what you have said, this is how I mentally process the terms:
    >
    > . A modifiable lvalue is any expression which _could_ have a meaningful
    > result if it appeared on the LHS of an assignment.
    > . A non-modifiable lvalue is any expression which _would_ be a
    > modifiable lvalue if it weren't const.
    > . An rvalue is any expression which isn't an lvalue.
    > . If an lvalue occurs in a context which does not require an lvalue, it
    > is evaluated to produce an rvalue.
    >
    > Granted, that definitely isn't how the C Standard uses or defines the
    > terms, but aside from that, is it accurate enough for someone other than
    > a compiler author? Or is there some subtle flaw in there that will bite
    > me someday?


    Your definition of "rvalue" directly contradicts the standard's
    definition; an "rvalue" is not an expression, it's the result of
    evaluating an expression.

    I'd probably drop your third bullet and replace "rvalue" by "value" in
    the fourth.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Nokia
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, Apr 7, 2010
    #12
  13. Nicklas Karlsson

    Phil Carmody Guest

    "bartc" <> writes:
    > "Nicklas Karlsson" <> wrote in message
    > news:...
    >> Hello,
    >>
    >> I am quite confused about this, so I split it in to subquestions, here
    >> we go:
    >>
    >> 1. Is an lvalue the expression itself, or is it the result yielded by
    >> evaluation of an expression? Take this for example: int i = 10; int *p
    >> = &i; and then dereference: *p; is the expression "*p" the thing you
    >> call an lvalue or is an lvalue the result yielded by evaluating that
    >> lvalue-expression?

    >
    > A rule of thumb might be: if you can apply the & operator to it
    > (address-of), then it can be an lvalue (with a few exceptions such as
    > function names)
    >
    > But here:
    >
    > int A,B;
    >
    > A = B;
    >
    > Both A,B could be lvalues, but only A is being used as one. (In assembly,
    > you will find little difference between how the two are treated:
    >
    > mov [A], # assuming memory-to-memory allowed
    >
    > (I'm done a bit of compiler work; I would handle the assignment above as
    > follows:
    >
    > *(&A) = B;


    So you'd not want your variables in registers? Why on earth not?

    Phil
    --
    I find the easiest thing to do is to k/f myself and just troll away
    -- David Melville on r.a.s.f1
     
    Phil Carmody, Apr 7, 2010
    #13
  14. Nicklas Karlsson

    Stefan Ram Guest

    Nicklas Karlsson <> writes:
    >1. Is an lvalue the expression itself, or is it the result yielded by


    An lvalue is an expression.

    >2. Rvalues, is rvalues the result yielded by an rvalue-expression, or
    >is it the expression itself? If its the result yielded by evaluation
    >of an rvalue-expression is an rvalue a plain value?


    An rvalue is the value of an expression (the value of the
    expression except when it is the operand of the sizeof
    operator, the unary & operator, the ++ operator, the --
    operator, or the left operand of the . operator or an
    assignment operator [possibly parenthesized]).

    >the example of *p, the lvalue will be of type "int", if an lvalue-
    >expression always yields an address when evaluated, C could keep track


    An lvalue designates an object, it does not have to
    have a pointer type.
     
    Stefan Ram, Apr 7, 2010
    #14
  15. Nicklas Karlsson

    Stefan Ram Guest

    -berlin.de (Stefan Ram) writes:
    >An lvalue is an expression.


    Having read parts of the discussion:

    I'd put it in these words, if I was invited to write a
    specification for the language C:

    Every expression might designate an object and/or a
    value. (For the definition of the object and the value,
    see the chapter "expressions", where this is specified
    for each type of expression.)

    Every operator can require each of its operands to
    designate an object and/or a value. (See the chapter
    "expressions", where this is specified for each
    operator.)

    For example, the assignment operator »=« requires its
    left operand to designate an object and its right
    operand to designate a value. It then writes this value
    into that object.
     
    Stefan Ram, Apr 7, 2010
    #15
  16. -berlin.de (Stefan Ram) writes:
    > -berlin.de (Stefan Ram) writes:
    >>An lvalue is an expression.

    >
    > Having read parts of the discussion:
    >
    > I'd put it in these words, if I was invited to write a
    > specification for the language C:
    >
    > Every expression might designate an object and/or a
    > value. (For the definition of the object and the value,
    > see the chapter "expressions", where this is specified
    > for each type of expression.)
    >
    > Every operator can require each of its operands to
    > designate an object and/or a value. (See the chapter
    > "expressions", where this is specified for each
    > operator.)
    >
    > For example, the assignment operator »=« requires its
    > left operand to designate an object and its right
    > operand to designate a value. It then writes this value
    > into that object.


    Clarification: All expressions designate values; only some expressions
    designate objects.

    And of course some expressions that are lvalues may not designate
    objects depending on the values of certain subexpresions; ``*ptr''
    designates an object if and only if ptr happens to contain a valid
    non-null address.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Nokia
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, Apr 7, 2010
    #16
  17. Nicklas Karlsson

    Guest

    Keith Thompson <> wrote:
    >
    > What the standard probably should say is "if an lvalue does not
    > designate an object when it is evaluated *in a context that requires
    > an lvalue*, the behavior is undefined.


    Isn't that addition redundant? I can't think of *any* context where an
    lvalue that doesn't desginate an object can be safely evaluated.
    --
    Larry Jones

    I'm a genius. -- Calvin
     
    , Apr 7, 2010
    #17
  18. Nicklas Karlsson

    Guest

    Stephen Sprunk <> wrote:
    >
    > . A non-modifiable lvalue is any expression which _would_ be a
    > modifiable lvalue if it weren't const.


    An array is a non-modifiable lvalue but is not const (only the elements
    can be const in C, not the array itself).
    --
    Larry Jones

    I don't want to be THIS good! -- Calvin
     
    , Apr 7, 2010
    #18
  19. Let me summarize what I make of this (hopefully its correct):

    What is an lvalue?
    An expression that designates (identifies) an object, when evaluated
    the compiler knows what object is being designated and what type that
    object has.

    What is an rvalue?
    The result of an expression that is not an lvalue appearing in LHS (an
    lvalue, when evaluated, yields an rvalue if it appears on RHS, that
    is, the value of the object being designated is being fetched, however
    if its on LHS it does not evaluate to an rvalue but rather evaluates
    so the compiler knows where to store an rvalue, that is, it identifies
    an object and what type that object has).

    What is an object?
    A region of data storage, usally an object is a place in memory, so it
    usally has a starting address, but it could also be stored in other
    ways, for example in the CPU's register and therefor won't have an
    ordinary address.

    Silly question, the lvalue (expression) itself has no type right? But
    when its evaluated the compiler finds out what type the object that
    the lvalue identifies has?
     
    Nicklas Karlsson, Apr 7, 2010
    #19
  20. Nicklas Karlsson <> writes:
    > Let me summarize what I make of this (hopefully its correct):
    >
    > What is an lvalue?
    > An expression that designates (identifies) an object, when evaluated
    > the compiler knows what object is being designated and what type that
    > object has.


    Close. Evaluation happens at run time; the compiler doesn't
    necessarily know which object is being designated. It does know
    the type of the object -- or rather the type imposed by the lvalue.
    This might not be the declared type of the object itself. In fact,
    the object might not even have a declared type.

    Some examples (I haven't taken the time to test these):

    int x, y, *ptr;
    switch (rand() % 3) {
    case 0: ptr = NULL; break;
    case 1: ptr = &x; break;
    case 2: ptr = &y; break;
    }
    *ptr; /* an lvalue, but the compiler has no idea whether it
    designates x, y, or no object at all */

    void *vptr = malloc(sizeof(int));
    assert(vptr != NULL);
    /* We've just created an object, but it has no inherent type. */
    *(int*)vptr; /* the type is imposed by the lvalue */
    *(unsigned*)vptr; /* same object, different lvalue, different type */


    > What is an rvalue?
    > The result of an expression that is not an lvalue appearing in LHS (an
    > lvalue, when evaluated, yields an rvalue if it appears on RHS, that
    > is, the value of the object being designated is being fetched, however
    > if its on LHS it does not evaluate to an rvalue but rather evaluates
    > so the compiler knows where to store an rvalue, that is, it identifies
    > an object and what type that object has).


    Too many words. An rvalue is the value of an expression, that's all.
    It's also a term that the Standard doesn't use, and I see little point
    in using it while discussing C. <OT>(C++ is another matter.)</OT>

    > What is an object?
    > A region of data storage, usally an object is a place in memory, so it
    > usally has a starting address, but it could also be stored in other
    > ways, for example in the CPU's register and therefor won't have an
    > ordinary address.


    I'd say "address" rather than "starting address". In C, an address is
    typed. It doesn't point to the beginning of an object, it points to
    the object.

    > Silly question, the lvalue (expression) itself has no type right? But
    > when its evaluated the compiler finds out what type the object that
    > the lvalue identifies has?


    No, an lvalue, like any expression, has a type.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Nokia
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, Apr 7, 2010
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Steven T. Hatton
    Replies:
    11
    Views:
    692
    Alf P. Steinbach
    Apr 20, 2004
  2. Replies:
    6
    Views:
    520
    Rolf Magnus
    Jun 8, 2005
  3. Lvalues and Rvalues

    , Oct 14, 2006, in forum: C Programming
    Replies:
    3
    Views:
    365
    SM Ryan
    Oct 14, 2006
  4. Steven T. Hatton

    cv-qualified rvalues

    Steven T. Hatton, Dec 14, 2006, in forum: C++
    Replies:
    1
    Views:
    823
    Victor Bazarov
    Dec 14, 2006
  5. jacob navia

    casts and lvalues

    jacob navia, Jun 24, 2007, in forum: C Programming
    Replies:
    68
    Views:
    1,435
    Keith Thompson
    Jun 27, 2007
Loading...

Share This Page