1

I have the program given below

#include<stdio.h>
int main()
{
   int i=5;
   (++(++i));
}

This program compiles fine in c++ but not in c. I couldn't truly understand either. But I've tried reading and searching and found that this is because preincrement operator returns rvalue in c and lvalue in c++.

If I change (++(++i)) to (++(i++)) then compilation fails in both in c and c++ because post-increment always returns rvalue.

Even after some reading, I don't get a clear picture of what exactly lvalue and rvalue mean here. Can somebody explain me in layman terms what are these?

dbush
  • 205,898
  • 23
  • 218
  • 273
Raman
  • 2,735
  • 1
  • 26
  • 46
  • 1
    `lvalue` is something that can be assigned to. `rvalue` is something that can be assigned. – Eugene Sh. Aug 16 '16 at 19:50
  • 1
    Not sure if this is too broad to be a duplicate, but you can probably find the answer here: http://stackoverflow.com/questions/3601602/what-are-rvalues-lvalues-xvalues-glvalues-and-prvalues – juanchopanza Aug 16 '16 at 19:50
  • To take `int i=5;` as example: `i` is an lvalue, because it can stand left of `=`. 5 is not an lvalue, so you can't write `5 = i;` (and there are prvalue, xvalues, etc.etc.) – deviantfan Aug 16 '16 at 19:50
  • 2
    Parentheses [do not add sequence points](https://stackoverflow.com/questions/22817517/do-parentheses-force-order-of-evaluation-and-make-an-undefined-expression-define) so your code exhibits [undefined behavior](https://stackoverflow.com/questions/4176328/undefined-behavior-and-sequence-points), so even if it compiled the runtime behavior is indeterminate and your program is ill-formed. – Cory Kramer Aug 16 '16 at 19:51
  • I've already read that link before asking here. But I still don't understand when one says "pre increment returns rvalue in c". I also don't understand how it affects my expression here. – Raman Aug 16 '16 at 19:53
  • @EugeneSh., To make that more confusing: http://coliru.stacked-crooked.com/a/0c9726f00d2d3ec5 The result of calling the function is an rvalue (a prvalue), yet it can still be assigned to. – chris Aug 16 '16 at 19:53
  • @ARBY Well, usually you can't modify an rvalue. – juanchopanza Aug 16 '16 at 19:55
  • @CoryKramer I believe `(++(++i))` is not that case. – LogicStuff Aug 16 '16 at 19:57
  • 1
    @juanchopanza Ok. Now what it means when we say "pre increment and post increment both returns rvalue in C". – Raman Aug 16 '16 at 19:58
  • @CoryKramer It's well-defined in C++11, and it would be in C11 too if ++i were hypothetically an lvalue in C. – Brian Bi Aug 16 '16 at 19:59
  • @ARBY It means exactly that. Which part don't you understand? `++i` is an rvalue in C, so you can't apply `++` to it. – juanchopanza Aug 16 '16 at 19:59
  • @CoryKramer What about `(++(++i));` is UB? – NathanOliver Aug 16 '16 at 20:00
  • @juanchopanza how can ++i return a rvalue? what is the rvalue here? what is the lvalue here? – Raman Aug 16 '16 at 20:01
  • @ARBY "returning" is probably the wrong terminology. The expressions `++i` and `i++` are rvalues in C. That is specified by the language so that's that. – juanchopanza Aug 16 '16 at 20:02
  • @juanchopanza but if rvalue exists, lvalue must also exist and an `=` sign must exist in between by definition of rvalue and lvalue. There is no assignment operation here. – Raman Aug 16 '16 at 20:05
  • 2
    @ARBY `5` is an rvalue. Where is the lvalue? – juanchopanza Aug 16 '16 at 20:05
  • 1
    @ARBY The = is just a test, there doesn't have to be one. A lvalue is something that can be assigned to. A rvalue is something that cannot. – NathanOliver Aug 16 '16 at 20:06
  • @NathanOliver Oh I get the idea now. Thank you NathanOliver and juanchopanza. – Raman Aug 16 '16 at 20:09
  • ++(++i) compiled, you claim? – Bruce David Wilner Aug 16 '16 at 20:13
  • @BruceDavidWilner yes in c++ and no in c. – Raman Aug 16 '16 at 20:14
  • "This program compiles fine in c++ but not in c" - Why do you expect **different** languages behave the same? For instance, there is no "rvalue" in the C standard. It explicitly uses a different term, which should be more clear to you. See footnote 64 in the standard. – too honest for this site Aug 16 '16 at 20:32

4 Answers4

3

"An lvalue (locator value) represents an object that occupies some identifiable location in memory (i.e. has an address).

rvalues are defined by exclusion, by saying that every expression is either an lvalue or an rvalue. Therefore, from the above definition of lvalue, an rvalue is an expression that does not represent an object occupying some identifiable location in memory."

reference: http://eli.thegreenplace.net/2011/12/15/understanding-lvalues-and-rvalues-in-c-and-c

Based on that definition, the post-increment i++ won't work anymore because the expression returned is not located in i anymore since it's incremented.

Meanwhile the expression returned by ++i returns a reference to the incremented variable i

Community
  • 1
  • 1
FreeStyle4
  • 272
  • 6
  • 17
3

In c the postfix or prefix ++ operators require that the operand is a modifiable lvalue. Both operators perform an lvalue conversion, so the object is no longer an lvalue.

C++ also requires that the operand of the prefix ++ operator is a modifiable lvalue, but the result of the prefix ++ operator is an lvalue. This is not the case for the postfix ++ operator.

Therefore (++(++i)); compiles as the second operation gets an lvalue, but (++(i++)) doesn't.

2501
  • 25,460
  • 4
  • 47
  • 87
2

Rvalues are essentially raw values or temporary results of an operation, they should not be operated on. So pre- or post-increment operations on these are not allowed.

Lvalues are traditional values that refer to a stored object, function or primitive, things which can be operated on or called.

In your first line: int i=5; // i is an lvalue, 5 is an rvalue

So, ++(i++) is translating to ++6, which is essentially what the compiler is complaining about.

Btw, this was already answered here: What are rvalues, lvalues, xvalues, glvalues, and prvalues?

Community
  • 1
  • 1
flu
  • 546
  • 4
  • 11
0
"lvalue" and "rvalue" are so named because of where each 
  of them can appear in an assignment operation.  An 
  lvalue 
 can appear on the left side of an assignment operator, 
  whereas an rvalue can appear on the right side.

  As an example:

int a;
a = 3;

In the second line, "a" is the lvalue, and "3" is the rvalue.

 in this example:



int a, b;
a = 4;
b = a;

In the third line of that example, "b" is the lvalue, and "a" is 
the rvalue, whereas it was the lvalue in line 2.  This 
illustrates an important point: An lvalue can also be an 
rvalue, but an rvalue can never be an lvalue.

Another definition of lvalue is "a place where a value can 
be stored."