lvalue and rvalue?

Discussion in 'C Programming' started by Zach, Jan 10, 2009.

1. ZachGuest

int x;
x = 10;

here x is the lvalue (the object holding a value) and 10 is the rvalue
(the value being assigned to an object) correct?

zach

Zach, Jan 10, 2009

2. Magnus BrandGuest

Zach wrote:
> int x;
> x = 10;
>
> here x is the lvalue (the object holding a value) and 10 is the rvalue
> (the value being assigned to an object) correct?

That's true. In K&R-2 it is stated that "An object is a named region of
storage; an lvalue is an expression referring to an object". So in your
example, 'x' is the expression and 10 the actual object.
An exception to this are arrays, since the name of an array itself is an
expression but can't be modified. So can refer to it as an "unmodofiable
lvalue".

Magnus

Magnus Brand, Jan 10, 2009

3. Keith ThompsonGuest

Zach <> writes:
> int x;
> x = 10;
>
> here x is the lvalue (the object holding a value) and 10 is the rvalue
> (the value being assigned to an object) correct?

The meanings of the terms "lvalue" and "rvalue" can be tricky.

Before C existed, the terms "lvalue" and "rvalue" referred to two
different ways of evaluating an expression. The 'l' and 'r' stand for
"left" and "right", as in the left and right sides of an assignment
statement. Evaluating an expression for its lvalue meant determining
what object it designates. Evaluting an expression for its rvalue
meant determining the value of the expression.

For example, given the declaration "int x;" evaluating the expression
``x'' would mean determining the object to which it refers -- without
accessing that object's value. In an exprssion like arr[func() + 3],
this can involve more than just resolving a name. Evaluating the
expression ``x'' for its rvalue would mean accessing the object to
obtain the value stored in it. Some expressions, such as ``x + 1'',
cannot be evaluated for their lvalues, because they don't refer to any
object.

The C standard changed the way the term "lvalue" is used, and almost
entirely dropped the term "rvalue". In C, an "lvalue" is not the
result of evaluating an expression, it's the expression itself. The
only mention of "rlvalue" is in a footnote, which says that it just
means the value of an expression. An expression that's not an lvalue
isn't referred to as a rvalue; it's just a non-lvalue expression.

An lvalue in C is basically an expression that designates an object.
Just to add to the frivolity, the C89/C90 standard's definition of
"lvalue" was worded incorrectly, and the C99 standard's revised
definition attempted to correct it but just made a mess of the whole
thing. (The mess is the result of trying to nail down case like *ptr,
where ptr is a pointer that doesn't currently point to an object.
*ptr is still an lvalue, but trying to use it as one invokes undefined
behavior. In two attempts, the standard has failed to express that
correctly.)

x = 10;
the subexpression x is an lvalue, and is used as an lvalue, because it
designates the object named "x".

Given:

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

In the assignment, both subexpressions x and y are lvalues, because
they're both expressions that designate objects. But y is not being
used as an lvalue; it's in a context, the right hand side of an
assignment, that doesn't require an lvalue. So the fact that it's an
lvalue is incidental. The left side of an assignment is a context
that does require an lvalue, so this:

(x + 1) = y;

is illegal (a constraint violation).

Sorry to have to give such a long explanation, but your question
wasn't as simple as it appeared (or as it should be).

--
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, Jan 10, 2009
4. Keith ThompsonGuest

Magnus Brand <> writes:
> Zach wrote:
>> int x;
>> x = 10;
>> here x is the lvalue (the object holding a value) and 10 is the
>> rvalue
>> (the value being assigned to an object) correct?

>
> That's true. In K&R-2 it is stated that "An object is a named region
> of storage; an lvalue is an expression referring to an object".

So x is an lvalue, but an lvalue is an expression, not an object.

> So in
> your example, 'x' is the expression and 10 the actual object.

'x', '10', and 'x = 10' are all expressions. 10 is not an object.

> An exception to this are arrays, since the name of an array itself is
> an expression but can't be modified. So can refer to it as an
> "unmodofiable lvalue".

Right, an array name is an unmodifiable lvalue. (An array *object* is
not an lvalue; it's an object.)

--
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, Jan 10, 2009
5. Magnus BrandGuest

Keith Thompson wrote:
> So x is an lvalue, but an lvalue is an expression, not an object.
> 10 is not an object.

I never said an lvalue was an object.
But why isn't '10' an object? I thought a data object was just a region
in memory that contains one value (or several values). So you've got a,
e.g. 4 bytes long memory section that holds this value.

I bid for rectification.

Magnus

Magnus Brand, Jan 11, 2009
6. Keith ThompsonGuest

Magnus Brand <> writes:
> Keith Thompson wrote:
>> So x is an lvalue, but an lvalue is an expression, not an object.
>> 10 is not an object.

> I never said an lvalue was an object.

The original poster more or less did:

here x is the lvalue (the object holding a value)

> But why isn't '10' an object? I thought a data object was just a
> region in memory that contains one value (or several values). So
> you've got a, e.g. 4 bytes long memory section that holds this value.

The context was an assignment:

x = 10;

An "object" is, by definition, a "region of data storage in the
execution environment, the contents of which can represent values".
10 is a value, not an object. It's not necessarily stored in memory.
In particular, it has no address.

An implementation might choose to store it in memory, but that's an
implementation detail that doesn't affect the question of whether it
can formally be considered to be an object. For example, the CPU
might have a "store ten in specified location" instruction.

--
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, Jan 11, 2009
7. James KuyperGuest

Magnus Brand wrote:
> Keith Thompson wrote:
> > So x is an lvalue, but an lvalue is an expression, not an object.
> > 10 is not an object.

> I never said an lvalue was an object.
> But why isn't '10' an object? I thought a data object was just a region
> in memory that contains one value (or several values). So you've got a,
> e.g. 4 bytes long memory section that holds this value.

The key point is that use of the integer literal 10 does not actually
require that a piece of memory be set aside to store a value of 10. If
you write 10*x, an implementation could just build that value (directly
or indirectly) into the executable code that performs the multiplication.

For instance, I've heard that there are some implementations which might
(under the right circumstances) generate code for 10*x which would be
equivalent to 8*x+2*x, or in other words, x<<3 + x<<1. On the hardware
these implementations were intended for, the two shifts and the addition
execute faster than the multiply, and the equivalent of the '3' and the
'1' are stored directly as part of the shift instruction. Its been so
long since I heard this that I can't remember what the target hardware
was; and it's quite possible that there are no longer any machines where
this would be a good idea; but that's irrelevant to my point. Even if
there were no such implementation, it would still be the case that such
an implementation would be perfectly conforming, and that IS my point.

James Kuyper, Jan 11, 2009
8. Ian CollinsGuest

Magnus Brand wrote:
> Keith Thompson wrote:
>> So x is an lvalue, but an lvalue is an expression, not an object.
>> 10 is not an object.

> I never said an lvalue was an object.
> But why isn't '10' an object? I thought a data object was just a region
> in memory that contains one value (or several values). So you've got a,
> e.g. 4 bytes long memory section that holds this value.
>

In addition to Keith's points, how do you propose assigning a value to '10'?

--
Ian Collins

Ian Collins, Jan 11, 2009
9. Stephen SprunkGuest

James Kuyper wrote:
> For instance, I've heard that there are some implementations which might
> (under the right circumstances) generate code for 10*x which would be
> equivalent to 8*x+2*x, or in other words, x<<3 + x<<1. On the hardware
> these implementations were intended for, the two shifts and the addition
> execute faster than the multiply, and the equivalent of the '3' and the
> '1' are stored directly as part of the shift instruction. Its been so
> long since I heard this that I can't remember what the target hardware
> was; and it's quite possible that there are no longer any machines where
> this would be a good idea; but that's irrelevant to my point. Even if
> there were no such implementation, it would still be the case that such
> an implementation would be perfectly conforming, and that IS my point.

Actually, turning multiplication and division by a constant into
shifting, addition, and/or subtraction is a very common optimization, or
at least the base of one.

For example, GCC turns "y = x * 10" into the following on my machine:

y = x;
y <<= 2;
y += x;
y += y;

That's pretty clever for "no" optimization. If I turn it up a notch:

y = x*4 + x;
y += y;

(x86's LEA instruction can do a*b+c iff b is a constant power of two.
convention is to write it as a multiply-add.)

S

--
Stephen Sprunk "Stupid people surround themselves with smart
CCIE #3723 people. Smart people surround themselves with
K5SSS smart people who disagree with them." --Isaac Jaffe

Stephen Sprunk, Jan 11, 2009
10. Magnus BrandGuest

Ian Collins wrote:
> In addition to Keith's points, how do you propose assigning a value to '10'?

You can't because as a it's always an rvalue, I'd say. Assignments are
the reason why lvalues exist.

Magnus

Magnus Brand, Jan 11, 2009
11. Phil CarmodyGuest

Keith Thompson <> writes:
> Magnus Brand <> writes:
>> Keith Thompson wrote:
>>> So x is an lvalue, but an lvalue is an expression, not an object.
>>> 10 is not an object.

>> I never said an lvalue was an object.

>
> The original poster more or less did:
>
> here x is the lvalue (the object holding a value)
>
>> But why isn't '10' an object? I thought a data object was just a
>> region in memory that contains one value (or several values). So
>> you've got a, e.g. 4 bytes long memory section that holds this value.

>
>
> The context was an assignment:
>
> x = 10;
>
> An "object" is, by definition, a "region of data storage in the
> execution environment, the contents of which can represent values".
> 10 is a value, not an object. It's not necessarily stored in memory.
> In particular, it has no address.

But c.f.
register int x=10; /* x also isn't /necessarily/ stored in memory */

However that example doesn't contradict the quoted definition in any way.

> An implementation might choose to store it in memory, but that's an
> implementation detail that doesn't affect the question of whether it
> can formally be considered to be an object. For example, the CPU
> might have a "store ten in specified location" instruction.

And in fact some of the less brain-dead architectures I've
worked with do.

Phil
--
I tried the Vista speech recognition by running the tutorial. I was
amazed, it was awesome, recognised every word I said. Then I said the
wrong word ... and it typed the right one. It was actually just
detecting a sound and printing the expected word! -- pbhj on /.

Phil Carmody, Jan 11, 2009
12. Keith ThompsonGuest

Phil Carmody <> writes:
> Keith Thompson <> writes:

[...]

[...]
>>
>> The context was an assignment:
>>
>> x = 10;
>>
>> An "object" is, by definition, a "region of data storage in the
>> execution environment, the contents of which can represent values".
>> 10 is a value, not an object. It's not necessarily stored in memory.
>> In particular, it has no address.

>
> But c.f.
> register int x=10; /* x also isn't /necessarily/ stored in memory */
>
> However that example doesn't contradict the quoted definition in any way.

Good point. My statement that "Objects have addresses." was an
over-generalization. Bit fields are another exception.

"data storage" is not necessarily addressible memory.

[...]

--
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, Jan 11, 2009
13. CBFalconerGuest

James Kuyper wrote:
>

.... snip ...
>
> For instance, I've heard that there are some implementations which
> might (under the right circumstances) generate code for 10*x which
> would be equivalent to 8*x+2*x, or in other words, x<<3 + x<<1. On
> the hardware these implementations were intended for, the two
> shifts and the addition execute faster than the multiply, and the
> equivalent of the '3' and the '1' are stored directly as part of
> the shift instruction. ...

That's just a means of implementing the multiply. The basic
requirements, to ensure it is worthwhile, is that one of the
operands is a constant, and that that operand can be represented as
the sum or difference of two binary powers. For example, if the
constant in binary is 0000011100 that can be represented by (32 *
OP2) - (4 * OP2), and the 32 and 4 are achieved by shifting.
Similarly 0001000010 is represented by (2 * OP2) + (64 * OP2).
Very useful when the machinery has no multiply instruction, and a
routine must be called. To keep the number of shifts down, just
insist the multiplier is less than some suitable constant before
generating that code.

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>

CBFalconer, Jan 12, 2009
14. Kaz KylhekuGuest

On 2009-01-11, Magnus Brand <> wrote:
> Ian Collins wrote:
>> In addition to Keith's points, how do you propose assigning a value to '10'?

> You can't because as a it's always an rvalue, I'd say. Assignments are
> the reason why lvalues exist.

You can use lvalues to access objects. Or to take the address which is later
used perhaps only for accessing, and not modifying.

Lvalues don't even have to be modifiable, and only the modifiable ones
can be assigned to.

An expression that designates an array is an lvalue. Does that exist
for the sake of assigning to an array?

Kaz Kylheku, Jan 12, 2009
15. Kaz KylhekuGuest

On 2009-01-11, Han from China - Master Troll <>
wrote:
> Keith Thompson wrote:

>
> I don't recommend that the OP listen to Keith Thompson. He's had
> a habit in recent days of making erroneous statements. Or maybe it's
> just that I've decided to start pointing them out.
>
> If objects are guaranteed addresses, then the standard wouldn't take
> pains to use the phrase "non-bitfield objects".

You're looking too hard. Your points are easily supported by the
definitions section.

> take pains to make certain exceptions for objects declared with the
> storage-class specifier 'register'.

3.5 bit: unit of data storage in the execution environment large enough
to hold an object that may have one of two values.

3.14 object: region of data storage in the execution environment,
the contents of which can represent values.

I seem to recall C90 objects being addressable by definition, but that's
clearly not the case now.

Kaz Kylheku, Jan 12, 2009