7

I tried this on my gcc:

int a=1;
cout<<(--a)--;

and the output is 0; but change it to

cout<<--(a--);

results in an error (lvalue required as decrement operand). Could someone enlighten me about this?

Thanks!

zw324
  • 26,764
  • 16
  • 85
  • 118
  • 3
    **Don't just tell us you have an error, tell us what that error is!** (If you had, I'd have upvoted, but without that, it can't be a good question.) – Fred Nurk May 20 '11 at 03:21
  • Now that I take a look upon it, it says "lvalue required as decrement operand". – zw324 May 20 '11 at 03:21
  • @Fred Nurk Thanks for the comment. Edited already:) – zw324 May 20 '11 at 03:22
  • 2
    _Always_ read the errors, and if you don't understand it look it up. The first page returned by copy-and-paste-ing that error text into Google has the answer to your question. – Chris Lutz May 20 '11 at 03:26
  • 2
    This is one of the most commonly asked class of questions on SO. Start at http://stackoverflow.com/questions/1525187/how-do-we-explain-the-result-of-the-expression-xxx and see the "linked" sidebar, you'll see many with lots of good answers. – Fred Nurk May 20 '11 at 03:27
  • @Fred Nurk Great link! THX :) – zw324 May 20 '11 at 03:30

3 Answers3

12

Both versions of ++ require lvalues as arguments, but the prefix version returns an lvalue as an argument, while the postfix version returns an rvalue.

Either way, you can't modify the same object twice between sequence points, so your "working" example invokes undefind behavior. The output can be whatever the compiler feels like doing. If you're just asking out of curiosity that's fine, but if this is relevant to your actual code you might be doing something wrong.

Chris Lutz
  • 73,191
  • 16
  • 130
  • 183
  • hang on a tick, if prefix increment doesn't count as a sequence point, why does it return an lvalue? (Note it doesn't in C) – Random832 May 20 '11 at 04:15
  • @Random832 - Because there's only about seven sequence points defined in C. None of the assignment operators are sequence points either. If you ask "why" it'll probably be "because that requires more overhead and makes the code potentially slower." – Chris Lutz May 20 '11 at 04:21
  • None of them return lvalues in C, though. What's the point of an lvalue you can't assign to? – Random832 May 20 '11 at 04:27
  • @Random832 - Yes they do. `(a = b) = c` compiles in G++. (Plain GCC actually emits an error that I don't know how to disable, which is a Good Thing, but it's still syntactically valid.) – Chris Lutz May 20 '11 at 05:05
8

predecrement --a decrements a, and then gives you back a itself. So you can then go on to modify it any way you want, including a postdecrement.

postdecrement a-- decrements a but gives you back a's value before the decrement. It's essentially giving you a copy of a. But you cannot then predecrement this copy. It's not an lvalue, so there's nothing to decrement. That's why it's an error.

Think of predecrement as returning a reference to a, and postdecrement as returning by constant value.

Tim
  • 8,912
  • 3
  • 39
  • 57
4
(--a)--

This is undefined behavior, as you modify the same object twice without an intervening sequence point. The compiler is not required to report when you invoke UB – it can't even detect UB in many situations. But if you turn on the right warnings (and you should look at what yours provides), it may be able to, sometimes.

--(a--)

Prefix decrement requires an lvalue, but postfix decrement returns an rvalue. This is an error that, unlike undefined behavior, the compiler is required to report.

Fred Nurk
  • 13,952
  • 4
  • 37
  • 63