5

When I use i++++ give compile error :

for (int i=1;i<=10;i++++) {} //a.cpp:63: error: lvalue required as increment operand

or

int i = 0;
i++++; // a.cpp:65: error: lvalue required as increment operand

but when I use ++++i is working. Anybody explain me why ++++i regular but i++++ not regular?

Thanks.

Elmi Ahmadov
  • 1,017
  • 5
  • 14
  • 25

5 Answers5

13

Since type of x is built-in primitive type, both expressions invoke undefined behaviour, as both attempt to modify the same object twice between two sequence points.

Don't do either of them.

Read this FAQ :

Undefined behavior and sequence points


However if the type of x is a user-defined type and you've overloaded operator++ for both expressions, then both would be well-defined.

For this, see this topic to know the explanation and details:

Undefined behavior and sequence points reloaded

Community
  • 1
  • 1
Nawaz
  • 353,942
  • 115
  • 666
  • 851
  • Wait, why is the preincrement one UB? – Xeo May 13 '11 at 05:14
  • @Xeo: both attempt to modify the object twice between two sequence points – Nawaz May 13 '11 at 05:15
  • Isn't `++++x` implemented as `x.operator++().operator++()` and as such not UB? – Xeo May 13 '11 at 05:16
  • @Xeo: `x` is not user-defined type! – Nawaz May 13 '11 at 05:17
  • Well, no reason not to implement it as that for primitive types. :P But really, the two increments are not sequenced? – Xeo May 13 '11 at 05:18
  • @Xeo: Are you trying to say that `operator++` can be implemented for primitive types as well? If so, then no, you cannot. – Nawaz May 13 '11 at 05:26
  • 1
    @Nawaz: Nono, just that the compiler devs could've done it that way. But it seems I'm wrong after all, no sequencing between the two increments on primitive types. – Xeo May 13 '11 at 05:30
  • `Since type of x is built-in primitive type, both expressions invoke undefined behaviour`. How does the expression `i++++` invoke UB? Its clearly ill-formed. If a compiler doesn't issue diagnostic for `i++++` its clearly broken. – Prasoon Saurav Apr 04 '12 at 11:23
  • @PrasoonSaurav: I think the question has been changed. – Nawaz Apr 05 '12 at 10:12
6

The C++ standard says in section 5.2.6 that the result of i++ is a modifiable lvalue, and in 5.3.2 that the result of ++i is a modifiable lvalue. This can help explain why i++++ and ++++i aren't required to generate diagnostics and can appear to work sometimes.

However, ++++i modifies i twice between the previous and next sequence points, so the result is still going to be undefined behaviour. ++++i is allowed to work but it doesn't have to.

Luckily for you, your compiler diagnosed i++++.

Windows programmer
  • 7,871
  • 1
  • 22
  • 23
  • Since I only have access to the C++0x FDIS, did this change? Because 5.2.6 of the FDIS says that the result of `i++` is a (p)rvalue and only talks about the operand (`i`) as being a modifiable lvalue. – Xeo May 13 '11 at 05:35
  • I have the version dated 2003. C99 does the same thing but with less wording. If it changed the change must have been some time ago. – Windows programmer May 13 '11 at 05:52
  • Okay, so `i++++` should be valid (but UB) in C++98/03, but is definitly invalid in C++0x/11. – Xeo May 13 '11 at 05:56
  • For your information, 5.2.6 in the final draft of current standard [here](http://www.kuzbass.ru:8086/docs/isocpp/expr.html) states _The result is an rvalue_. – Ise Wisteria May 13 '11 at 10:07
  • n3290 says that the result of i++ (i being primitive type) is a prvalue. So your answer is flawed! – Prasoon Saurav Apr 04 '12 at 11:27
5

Because the operators' conceptual "signatures" are:

​T& operator ++(T& a);​     // pre
​T operator ++(T& a, int);​ // post
                          // note the int is solely to distinguish the two

One returns a reference (an lvalue), and the other does not. Both, however, take a reference as their argument, so the one that returns a reference (++i) can be chained, and the one that does not (i++) cannot.

Note that, as @Nawaz said, the one that works invokes undefined behavior, as would the one that doesn't work in the hypothetical even that it did.

Community
  • 1
  • 1
Chris Lutz
  • 73,191
  • 16
  • 130
  • 183
  • The *type* in the question is built-in type. So `operator++` doesn't come into the picture. – Nawaz May 13 '11 at 05:23
  • @Nawaz - I was using that for illustrative purposes. I'm aware that built-in types don't use `operator++` for anything, but seeing the signatures helps understand the problem. – Chris Lutz May 13 '11 at 23:43
  • If built-in types don't have `operator++`, then how come it can explain the problem? If the object of illustration is itself wrong, then how can it illustrate anything correctly? – Nawaz May 14 '11 at 02:48
3

As some say, ++++i is accepted by your compiler, but when it's evaluated, it produces undefined behavior in C++03.

Note that simply saying sizeof(++++i) is fine, because nothing is evaluated. Saying ++++i is fine in C++11 even if it's evaluated.

Johannes Schaub - litb
  • 496,577
  • 130
  • 894
  • 1,212
2

To answer this from the "what you want to do" view: there is no point to calling i++++ to start with, because i++ does not return a reference to the incremented i variable, but the value i had before it was incremented. So i++++ would essentially do this:

  1. Copy i to a temporary variable t
  2. Increment i
  3. Copy t to a temporary variable u
  4. Increment t
  5. Throw away both t and u

So all that remains would be one increment of i.

On the other hand, ++++i does simply

  1. Increment i
  2. Increment i, again

and that can indeed be useful, not so much in an integer type but certainly when i is a non-random-access iterator, because then you can't rely on i+=2.

leftaroundabout
  • 117,950
  • 5
  • 174
  • 319