'Exact difference between rvalue and lvalue

While I was reading http://thbecker.net/articles/rvalue_references/section_01.html, I got following snippiest.

// lvalues:
//
int i = 42;
i = 43; // ok, i is an lvalue
int& foo();
foo() = 42; // ok, foo() is an lvalue
int* p1 = &foo(); // ok, foo() is an lvalue

// rvalues:
//
int foobar();
int j = 0;
j = foobar(); // ok, foobar() is an rvalue
int* p2 = &foobar(); // error, cannot take the address of an rvalue
j = 42; // ok, 42 is an rvalue

Why int* p2 = &foobar(); is error statement, while int* p1 = &foo(); is not an error. How later one is lvalue while first one is rvalue?



Solution 1:[1]

So we have two functions:

int& foo();
int foobar();
  • foo is a function returning lvalue-reference to int
  • foobar is a function returning int

The function call expressions:

foobar()
foo()

both have type int (references are removed from expressions, so foo() has type int and not lvalue-reference to int). The two expressions have different value categories:

  • foobar() is a prvalue (a function call to a function returning a non-reference is a prvalue)
  • foo() is an lvalue (a function call to a function returning an lvalue-reference is an lvalue)

You can't take the address of an rvalue (a prvalue is a kind of rvalue), so &foobar() is not allowed.

You can take the address of an lvalue so &foo() is allowed.

Solution 2:[2]

Suppose we have the example code shown below in C. Will it compile? How do the concepts of lvalues and rvalues work in this problem?

#define X 8
int main(void)
{
    ++X; // will this line compile?
        return 0;

}

The concept of lvalues and rvalues must be explained a bit in order to really understand the code above, and the problem being asked. Before we proceed, you should note that the definition of lvalues and rvalues presented here is not exact as even the C Standards themselves are rather vague on the definition.

The difference between rvalues and lvalues

An object is a region of memory that can be examined, but not necessarily modified. An lvalue is an expression that refers to such an object. The term lvalue originally referred to objects that appear on the left (hence the ‘l’) hand side of an expression. That definition no longer applies since any const-qualified type is also considered to be an lvalue, but it can never appear on the left hand side of an assignment statement because it can not be modified. So, the term "modifiable lvalue" was created to refer to an lvalue that can be modified, and a const-qualified type does not fall into this category.

An rvalue is any expression that has a value, but cannot have a value assigned to it. One could also say that an rvalue is any expression that is not an lvalue . An example of an rvalue would be a literal constant – something like ’8?, or ’3.14?. So, clearly the value ’8? in the code above is an rvalue.

Using our understanding of lvalues and rvalues to answer the question

Now let’s try to solve the problem. Strictly speaking, the operand of the prefix (or postfix) increment operator must be a modifiable lvalue. So, what is the operand of the prefix increment operator in our code above?

Since X is a macro, the statement above will expand to “++8? after the preprocessor is run. This means “8? is the operand of the prefix increment operator. And, because 8 is an rvalue it can not be used as an argument to “++”. This, in turn, means that the code above will not compile.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Community
Solution 2 Siva S Tenet