Re: returning lvalue in C vs C++



On 2006-03-30, Alf P. Steinbach <alfps@xxxxxxxx> wrote:
* Ben C:

f().x is _not_ an invalid lvalue, it's a perfectly good lvalue.

I'm sorry, that's incorrect -- it's not an lvalue at all, it's an rvalue.

What's your definition of lvalue and rvalue?

I just looked in K&R, and it says, "An _object_ is a named region of
storage; an _lvalue_ is an expression referring to an object. An obvious
example of an lvalue is an identifier with suitable type and storage
class [...]"

Not a precise definition, but I come away with the idea that lvalue is
storage, rvalue is what you store there.

I'm suggesting that another example of an lvalue is a structure instance
returned from a function, on the basis that a structure instance is
always an object. f().x is an expression referring to a region of
storage, and so you can assign to it. Values of variables of structure
types are objects, values of variables of builtin types are not, they're
rvalues.

The thing that's a bit "confusing" about C (although natural at the same
time) is that when you write an assignment:

x = 4;

You mean "store 4 in the storage region named x".

But when you write:

y = x;

x means something different: "the contents of the storage region named
x".

We just write "x" in both places, but we mean slightly different things.
In other languages, Tcl, bash, or make, for example, you'd use a $ in
front of the x in the second example, to indicate "the value stored in
region x" as opposed to "the storage region x itself".

So, in

f().x = 10;

f().x is the name of a storage region, but in y = f().x, it implicitly
means "what's stored there". The value of f() is a structure
instance, and therefore a region of storage.

The example below compiles and runs and prints out 20 using gcc -x c++,
but fails to compile with -x c.

Here we're assigning t to f(), and then reading back the value of f().x
into y. I can't see anything wrong with it.

#include <stdio.h>

struct thing
{
int x;
};

struct thing f(void)
{
struct thing ret = {10};
return ret;
}

int main(void)
{
struct thing t = {20};
int y = (f() = t).x;

printf("%d\n", y);

return 0;
}
.



Relevant Pages

  • Re: returning lvalue in C vs C++
    ... I'm sorry, that's incorrect -- it's not an lvalue at all, it's an rvalue. ... storage; an _lvalue_ is an expression referring to an object. ... struct thing f ...
    (comp.programming)
  • Re: string literal is an lvalue; other literals are rvalues.
    ... >> lvalue, but not of an rvalue. ... >> An lvalue denotes a storage location, an rvalue denotes a value sans ... > If I have a literal 5 in my source code it begins life as an ascii ...
    (comp.lang.cpp)
  • Re: gcc: pointer to array
    ... >>> fits the C99 definition of an Lvalue which does not refer ... of the relevant parts of) the standard, ... This "being found in storage" can be equated to taking the address of the ... Specifies that a decayed array is an rvalue, ...
    (comp.lang.c)
  • Re: r- r-value vs l-value?
    ... bis an lvalue ... a+5 is an rvalue ... an rvalue-to-lvalue conversion occurs (and this conversion is ... It expects an rvalue operand and yields an lvalue which designates the ...
    (comp.lang.c)
  • Re: string literal is an lvalue; other literals are rvalues.
    ... >> As I understand the distinction between rvalue and lvalue, ... but not of an rvalue. ... such as the int value 5. ... There is talk of lvalue to rvalue conversion in 4.1. ...
    (comp.lang.cpp)