Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why are multiple increments/decrements valid in C++ but not in C?

test.(c/cpp)

#include <stdio.h>

int main(int argc, char** argv)
{
  int a = 0, b = 0;
  printf("a = %d, b = %d\n", a, b);
  b = (++a)--;
  printf("a = %d, b = %d\n", a, b);

  return 0;
}

If I save the above as a .cpp file, it compiles and outputs this upon execution:

a = 0, b = 0
a = 0, b = 1

However, if I save it as a .c file, I get the following error:

test.c:7:12: error: lvalue required as decrement operator.

Shouldn't the (++a) operation be resolved before the (newValue)-- operation? Does anyone have any insight on this?

like image 227
mkosler Avatar asked Feb 10 '13 14:02

mkosler


People also ask

How do increments work in C?

In C/C++, Increment operators are used to increase the value of a variable by 1. This operator is represented by the ++ symbol. The increment operator can either increase the value of the variable by 1 before assigning it to the variable or can increase the value of the variable by 1 after assigning the variable.

How multiple increment and decrement operators work in C?

Difference between the Increment and Decrement Operator in C It is used to increment the value of a variable by 1. It is used to decrease the operand values by 1. The increment operator is represented as the double plus (++) symbol. The decrement operator is represented as the double minus (--) symbol.

Can we use increment operator in C?

The decrement (–) and increment (++) operators are special types of operators used in programming languages to decrement and increment the value of the given variable by 1 (one), respectively.

Does C have increment?

Preincrement and Postincrement in C are the two ways to use the increment operator. In Pre-Increment, the operator sign (++) comes before the variable. It increments the value of a variable before assigning it to another variable. In Post-Increment, the operator sign (++) comes after the variable.


3 Answers

In C the result of the prefix and postfix increment/decrement operators is not an lvalue.

In C++ the result of the postfix increment/decrement operator is also not an lvalue but the result of the prefix increment/decrement operator is an lvalue.

Now doing something like (++a)-- in C++ is undefined behavior because you are modifying an object value twice between two sequence points.

EDIT: following up on @bames53 comment. It is undefined behavior in C++98/C++03 but the changes in C++11 on the idea of sequence points now makes this expression defined.

like image 114
ouah Avatar answered Oct 08 '22 23:10

ouah


In C and C++, there are lvalue expressions which may be used on the left-hand side of the = operator and rvalue expressions which may not. C++ allows more things to be lvalues because it supports reference semantics.

++ a = 3; /* makes sense in C++ but not in C. */

The increment and decrement operators are similar to assignment, since they modify their argument.

In C++03, (++a)-- would cause undefined behavior because two operations which are not sequenced with respect to each other are modifying the same variable. (Even though one is "pre" and one is "post", they are unsequenced because there is no ,, &&, ?, or such.)

In C++11, the expression now does what you would expect. But C11 does not change any such rules, it's a syntax error.

like image 30
Potatoswatter Avatar answered Oct 08 '22 23:10

Potatoswatter


For anybody who might want the precise details of the differences as they're stated in the standards, C99, §6.5.3/2 says:

The value of the operand of the prefix ++ operator is incremented. The result is the new value of the operand after incrementation.

By contrast, C++11, §5.3.2/1 says:

The result is the updated operand; it is an lvalue, and it is a bit-field if the operand is a bit-field.

[emphasis added, in both cases]

Also note that although (++a)-- gives undefined behavior (at least in C++03) when a is an int, if a is some user-defined type, so you're using your own overloads of ++ and --, the behavior will be defined -- in such a case, you're getting the equivalent of:

a.operator++().operator--(0);

Since each operator results in a function call (which can't overlap) you actually do have sequence points to force defined behavior (note that I'm not recommending its use, only noting that the behavior is actually defined in this case).

like image 44
Jerry Coffin Avatar answered Oct 09 '22 01:10

Jerry Coffin