3
int x = 3;
int y = 5;
x++ = y;
cout << x << endl;

Why is the above code giving me an error, the specific error I get is

lvalue required as left operand of assignment.

I am trying to review up on my C and C++. From my understanding the above code should theoretically copy over the value of y into x, then finally increment the value of x after the copy has finished. So it would print out "6".

Jens Gustedt
  • 76,821
  • 6
  • 102
  • 177
AyBayBay
  • 1,726
  • 4
  • 18
  • 37

9 Answers9

6
x++ ==> x=x+1

x++ = y ==> (x+1)=y

now x+1=y will throw lvalue required which means left hand side of = should be a variable not a constant

AJ.
  • 4,526
  • 5
  • 29
  • 41
  • why is it that ++x = y works then? ++x should also map to x = x+1, I dont get it – AyBayBay Dec 31 '13 at 09:49
  • 2
    @AyBayBay Because when you do `++x`, first `x` is incremented.. then it get some value.. then, you overwrite this value with the value of `y`. – Maroun Dec 31 '13 at 09:51
  • @MarounMaroun dont you mean x gets the value of y? Arent you copying over y into x? – AyBayBay Dec 31 '13 at 09:53
  • @AyBayBay I think you are confused with `x++` and `++x` – AJ. Dec 31 '13 at 09:55
  • 1
    @AyBayBay: `++x = y` increments the value of `x` and throws it away by over-writing it with the value of `y`. – legends2k Dec 31 '13 at 09:55
  • @legends2k I guess my real confusion lies in this example. In the following case: "x = y++" Y will get copied over to X and then Y's value gets incremented. I do not see why the same cant apply to "x++ = y", like its not consistent. Maybe I have just been staring at this stuff too long and I am going crazy. I thought the post-increment operator waits for all actions/assignments to happen first, and then applies the increment. – AyBayBay Dec 31 '13 at 09:58
  • @AyBayBay try this `cout< – AJ. Dec 31 '13 at 10:01
  • @AJ.; Your answer suggests that compiler will throw error for `1 = y`. I disagree. Compiler will parse it as `(x++) = y`. Now `y` has nothing to do with `1`. – haccks Dec 31 '13 at 10:01
  • 1
    @AyBayBay: This is not maths where the side doesn't matter in equality; `x = y` means `y`'s value is assigned to `x`, and not `x` assigned to `y`. The side does matter in assignment operator. The same rationale applies for your question on why there's no symmetry in `x = y++` and `x++ = y`. The post-increment does await, but in the end it returns a value and not an address, so `x = (5+1)` makes sense while `(3 + 1) = 5` doesn't. – legends2k Dec 31 '13 at 10:04
  • 1
    @AyBayBay; `why is it that ++x = y works then?`: This will not work. At least in C. – haccks Dec 31 '13 at 10:08
  • 1
    @haccks: +1 Didn't know this subtle difference between C++ and C. Thanks! – legends2k Dec 31 '13 at 10:14
  • 2
    This answer seems to me wrong. (8 upvotes!). – haccks Dec 31 '13 at 10:25
  • 1
    This answer is also wrong. :( – Joseph Mansfield Dec 31 '13 at 10:32
  • The only things missing from this answer are perhaps a couple of parens, and sequence points. Conceptually, he has nailed the specific problem (the compilation error) of the OP on the head. – Puppy Dec 31 '13 at 10:40
  • @AyBayBay: ++x is an lvalue. x++ is an rvalue. This is because ++x can essentially return x, which is an lvalue, whereas x++ has to return an rvalue- the old value of x. C may not have had this nuance in it, but C++ assuredly does. – Puppy Dec 31 '13 at 10:41
  • 2
    @DeadMG I think this answer is implying that it is equivalent to `x=x+1=y` and so by associativity equivalent to `x=(x+1=y)`. Sure, the fact that `x+1` gives an rvalue is the same problem, but the explanation is not really true. – Joseph Mansfield Dec 31 '13 at 11:23
2

The result of the postincrement operator is a temporary object that has the value before incrementing. You may not assign a temporary object. So this statement is invalid.

x++ = y;

You could rewrite it the following way

( x += 1 ) = y;

The statement above is correct.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • 1
    Isn't `( x += 1 ) = y;` modifying `x` twice without an intervening sequence point? – fredoverflow Dec 31 '13 at 10:37
  • @legends2k I agree with you. But the problem is that the program has undefined bahaviour because operations x = x + 1 and x = y are not sequenced.:) – Vlad from Moscow Dec 31 '13 at 10:37
  • @legends2k Ah, well I was referring to the *explanation* part of the answer. :D – Joseph Mansfield Dec 31 '13 at 10:38
  • @FredOverflow: Certainly in C++03. I'm not sure what the C++11 rules have to say about this. – Puppy Dec 31 '13 at 10:38
  • @DeadMG As far as I can tell, it's not undefined in C++11. I just made a nice sequenced-before graph on paper. – Joseph Mansfield Dec 31 '13 at 10:51
  • Er, the left-hand-side of an assignment is sequenced-before the right-hand-side, right? – Puppy Dec 31 '13 at 10:52
  • @FredOverflow It is valid code for the both Standards because operands (the left and the right) shall be calculated before calculating the result of the operator – Vlad from Moscow Dec 31 '13 at 10:54
  • @ DeadMG, No, it is not. The both operands shall be calculated before the assignment. So at first will be calculated x += 1 and after that ( x += 1 ) = y – Vlad from Moscow Dec 31 '13 at 10:56
  • @sftrabbit You are wrong. According to the C++ Standard "In all cases, the assignment is sequenced after the value computation of the right and left operands, and before the value computation of the assignment expression." – Vlad from Moscow Dec 31 '13 at 11:07
  • @VladfromMoscow Sorry, changed my mind again. It's valid. Haha. I drew my graph wrong. – Joseph Mansfield Dec 31 '13 at 11:08
  • @VladfromMoscow I'm not convinced it's well-defined in C++03 though. It doesn't seem to *care* about the fact that operands must be evaluated before operators. It simply states: "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." So while conceptually this would be fine in C++03, the standard says it's undefined because there's no sequence point between them. – Joseph Mansfield Dec 31 '13 at 11:20
  • @sftrabbit It was a standard defect. In fact in the C++ 2003 Standard there is written "In simple assignment (=), the value of the expression replaces that of the object referred to by the left operand." The C++ 2011 Standard made simply this statement more clear. – Vlad from Moscow Dec 31 '13 at 11:33
1

From my understanding the above code should theoretically copy over the value of y into x, then finally increment the value of x after the copy has finished.

x++ evaluates to an r-value (constant). Assignment operator = needs an l-value (variable) as its left operand.

x++ = y ==> (3 + 1) = 5 ==> 4 = 5  

you can't assign a constant to a constant. x++ = y is not a valid statement in either of C or C++.

haccks
  • 104,019
  • 25
  • 176
  • 264
1

x++ cannot be use as left operand because it returns a value, not an address.

HAL9000
  • 3,562
  • 3
  • 25
  • 47
1

In this line:

x++ = y;

x++ is r-value, and you cannot assign to it, you can rewrite it as follows: 3 = 5; which makes no sense, you cannot assign 5 to 3.

marcinj
  • 48,511
  • 9
  • 79
  • 100
1

In your expression: x++ = y, x++ is just a result of an evaluated expression so you can't assigne a value to a result.

Another think is that this expression has no meaning since the variable x will be updated with the value of y.

rullof
  • 7,124
  • 6
  • 27
  • 36
1

The result of x++ is the value of x, but not the object x. The expression is a prvalue, which means you can't then assign to it (you need an lvalue).

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 result is a prvalue.

To achieve what you want, you need to do:

x = y;
x++;

In C++11, with its new sequencing rules, you could also do:

(x = y)++;

This would be undefined behaviour in C++03 because there is no sequence point between two modifications of x.

Joseph Mansfield
  • 108,238
  • 20
  • 242
  • 324
  • +1 I understand that `++x = y` is undefined since x is modified twice with no sequence point in between. Then why does C++, unlike C which prohibits both `x++ = y` and `++x = y`, allow the latter? Where does it makes sense to do `++x = y`? – legends2k Dec 31 '13 at 10:54
  • @legends2k Yeah, I can't think of a reason to do it. I suppose if the operators were overloaded in some weird way, there *could* be a reason. – Joseph Mansfield Dec 31 '13 at 11:10
0

x++ results in a temporary object that has x value before the increment. And you cannot assign a temp object.

Examples for clarification:

int a=1; 
a=5; // Lvalue = Rvalue, Ok 
a=a; // Lvalue = Lvalue, Ok 
5=a; // Rvalue = Lvalue Comp. error
5=5; // Rvalue = Rvalue Comp. error 
Maroun
  • 94,125
  • 30
  • 188
  • 241
  • 1
    This is wrong, since 1 is not the l-value compiler is complaining about, it's complaining about the temporary returned before incrementing the value at `x`. This temporary will have a value of `x` before increment and not `1`. – legends2k Dec 31 '13 at 10:22
  • 1
    This is also not how expressions work. `x++` is the subexpression, so it would be *almost* equivalent to `(x = x + 1) = y`. – Joseph Mansfield Dec 31 '13 at 10:29
  • @MarounMaroun: No, `it's like writing (x = x + 1) = y;` is wrong; `x++ = y` tries to assign `y` not to `x + 1` but to the temporary with value `x`. Read my first comment properly. – legends2k Dec 31 '13 at 10:46
  • @legends2k You are absolutely right. Thanks. – Maroun Dec 31 '13 at 10:50
0

The core issue is this:

From my understanding the above code should theoretically copy over the value of y into x, then finally increment the value of x after the copy has finished. So it would print out "6".

In fact, the sequencing of the increment is undefined. As in, it is completely undefined as to when x is incremented, except that it must occur before some specific times. Reading or writing x during this period of undefined value is undefined behaviour. That's why x++ does not return x (an lvalue you can write to) but an rvalue you cannot write to- because there's simply nothing useful you can do with x until the time it's guaranteed to be incremented (except take the address, maybe).

You can still break this rule by referring to x twice- for example, consider:

void f(int, int);
int main() {
    int x = 0;
    f(x++, x++);
}

This is also undefined behaviour.

Puppy
  • 144,682
  • 38
  • 256
  • 465