-1

In C++,

i = ++++j;

works fine in the code but when I use,

i = j++++;

I receive the following error:

Operand for operator "++" must be an lvalue.

Why am I getting this error?

Shafik Yaghmour
  • 154,301
  • 39
  • 440
  • 740
user2782405
  • 393
  • 1
  • 6
  • 20
  • If you must do it on one line then the clearest for me is `i = j += 2`. But I see no reason that this has to be completed on one line and therefore pippin1289 or Dyp suggestions are solid. – miltonb Sep 16 '13 at 02:25
  • 1
    Assuming `j` is a built-in type, `++++j` is undefined behavior. If it is a user defined type the expression is actually OK, though. Using the postincrement operator doesn't work, however, because you can't increment the temporary returned from `j++` for built-in types. It just compile for user-defined types, though, although the semantics are not quite obvious. – Dietmar Kühl Sep 16 '13 at 02:26
  • 1
    Is the word "value" in the title a typo or did you miss that it's saying "Lvalue"? – kfsone Sep 16 '13 at 02:29
  • 2
    Whatever it is that you're trying to do, I guarantee that `i = ++++j`; is not the best way to express it. – Keith Thompson Sep 16 '13 at 02:57
  • possible duplicate of [L-Value, Pointer arithmetic](http://stackoverflow.com/questions/18258745/l-value-pointer-arithmetic) – Grijesh Chauhan Oct 02 '13 at 18:50

2 Answers2

6

Post-increment requires that the operand should be a modifiable lvalue but the result of post-increment is a prvalue("pure" rvalue) which is not modifiable, this diagram shows what is going on:

i = (j++)++ ;
     ^  ^
     |  |
     |  Result is a prvalue, not a valid operand for subsequent post-increment
     Modifiable lvalue

Understanding lvalues and rvalues in C and C++ is a good place to start if you need to understand the difference between lvalues and rvalues. From the draft C++ standard section 5.2.6 Increment and decrement [expr.post.incr] paragraph 1 says(emphasis is mine in this an subsequent quotes):

The value of a postfix ++ expression is the value of its operand. [ Note: the value obtained is a copy of the original value —end note ] The operand shall be a modifiable lvalue. [..] The result is a prvalue.

Update

I reworked my language on undefined behavior since there is a difference here with respect to C++03 and C++11.

Although the first expression shown:

i = ++++j ;

does not generate an error but if this is C++03 and j is a fundamental type this is undefined behavior since modifying it's value more than once within a sequence point is undefined. The relevant section in an older draft standard would be section 5 Expressions paragraph 4 which says:

[...]Between the previous and next sequence point a scalar object shall have its stored value modified at most once by the evaluation of an expression. Furthermore, the prior value shall be accessed only to determine the value to be stored. The requirements of this paragraph shall be met for each allowable ordering of the subexpressions of a full expression; otherwise the behavior is undefined.

and it gives some examples, one of which is as follows:

i = ++i + 1; // the behavior is undefined

In C++11 the language changes to the side-effect on the same scalar object is unsequenced relative to the another side effect on the same object then the behavior is undefined. So this is actually well defined in C++11, in section 1.9 Program execution paragraph 15 says:

Except where noted, evaluations of operands of individual operators and of subexpressions of individual expressions are unsequenced. [...] If a side effect on a scalar object is unsequenced relative to either another side effect on the same scalar object or a value computation using the value of the same scalar object, the behavior is undefined.

Using post- and pre- increment in this way does not lead to readable(maintainable) code in both cases using j +=2 either before or after the assignment statement would have sufficed

Shafik Yaghmour
  • 154,301
  • 39
  • 440
  • 740
  • Is "i = ++i + 1;" really undefined behavior? One would think it just adds two to i, and indeed this is what it seems to do when I type into Dev-C++. –  Sep 16 '13 at 19:27
  • @philipwhite That example and quote comes straight from the standard so it is indeed undefined behavior if that standard says it is. I provided the link to the older close to 03 standard so you can look it up for yourself as well. – Shafik Yaghmour Sep 16 '13 at 19:30
  • Ok. +1 for teaching me something new. I think you inspired me to ask a question of my own.... –  Sep 16 '13 at 19:32
  • @philipwhite Just be ware that undefined behavior questions are asked a lot on SO(you may already know) and there are several canonical questions that cover this topic pretty well and so those types of questions usually get closed pretty quickly. – Shafik Yaghmour Sep 16 '13 at 19:47
  • Oops, oh well. Maybe it will be closed. –  Sep 16 '13 at 19:48
  • @philipwhite Here are some of the more commonly referenced answers [Undefined Behavior and Sequence Points](http://stackoverflow.com/questions/4176328/undefined-behavior-and-sequence-points) and [Could anyone explain these undefined behaviors (i = i++ + ++i , i = i++, etc…)](http://stackoverflow.com/questions/949433/could-anyone-explain-these-undefined-behaviors-i-i-i-i-i-etc) with respect to undefined behavior. – Shafik Yaghmour Sep 17 '13 at 03:32
1

you are getting this error because the postfix operator returns a value and not a reference. But for clarity you should probably not do i=j++++; it might be more clear to say i = j += 2; or separate the lines into i = j+2; j+=2; or j+=2; i = j;.

pippin1289
  • 4,861
  • 2
  • 22
  • 37
  • Thanks for your response. But I don't understand, what makes the line 1 to accept and for line 2, its a error? what is the difference? – user2782405 Sep 16 '13 at 02:30
  • This is because of what the operators return. The prefix operator will return a reference while the postfix operator returns a value. Values cannot be "incremented" as these operators modify objects in memory not temporary values. – pippin1289 Sep 16 '13 at 02:32
  • 1
    @user2782405: The key is in the value that the expression evaluates to (inherited from C). A pre-increment expression has the value *after* incrementation, which means it can be a reference to the the variable being incremented, because that is the value that the variable has. A post-increment expression has the value *before* incrementation, so it cannot be a reference to the variable being incremented, because the variable no longer has that value. – Benjamin Lindley Sep 16 '13 at 02:42