Multiple Preincrement Operations on a Variable in C++(C )

Multiple preincrement operations on a variable in C++(C ?)

That is because in C++ pre-increment operator returns an lvalue and it requires its operand to be an lvalue.

++++++++++phew ; in interpreted as ++(++(++(++(++phew))))

However your code invokes Undefined Behaviour because you are trying to modify the value of phew more than once between two sequence points.

In C, pre-increment operator returns an rvalue and requires its operand to be an lvalue. So your code doesn't compile in C mode.

Why are multiple pre-increments allowed in C++ but not in C?

C and C++ say different things about the result of prefix ++. In C++:

[expr.pre.incr]

The operand of prefix ++ is modified by adding 1. The operand shall be
a modifiable lvalue
. The type of the operand shall be an arithmetic
type other than cv bool, or a pointer to a completely-defined object
type. The result is the updated operand; it is an lvalue, and it is a
bit-field if the operand is a bit-field. The expression ++x is
equivalent to x+=1.

So ++ can be applied on the result again, because the result is basically just the object being incremented and is an lvalue. In C however:

6.5.3 Unary operators

The operand of the prefix increment or decrement operator shall have atomic, qualified, or unqualified real or pointer type, and shall be a modifiable lvalue.

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

The result is not an lvalue; it's just the pure value of the incrementation. So you can't apply any operator that requires an lvalue on it, including ++.

If you are ever told the C++ and C are superset or subset of each other, know that it is not the case. There are many differences that make that assertion false.

Pre-Increment Operators when Using the Variable on the Same Line

I would advice against using such "tricks" in your code in the long term this is maintenance nightmare and is hard to reason about. There are almost always alternatives, for example this code:

testStruct test = {a[++i], b[i]}

could be changed to:

++i ;
testStruct test = {a[i], b[i]}

So having said that, neither case uses the comma operator in both functions calls and intialization lists the comma is a grammar elements and nothing else.

Your first situation is well defined although there is some caveats depending on whether this is C++11 or pre C++11.

In both cases there is a sequence point after each comma, although pre C++11 the order of evaluation is not specified. So we can see this for the pre C++11 case by going to defect report 430 which says:

A recent GCC bug report (
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11633) asks about the
validity of

int count = 23;   int foo[] = { count++, count++, count++ };

is this undefined or unspecified or something else?

and the answer is (emphasis mine going forward):

I believe the standard is clear that each initializer expression in
the above is a full-expression
(1.9 [intro.execution]/12-13; see also
issue 392) and therefore there is a sequence point after each
expression (1.9 [intro.execution]/16). I agree that the standard does
not seem to dictate the order in which the expressions are evaluated
,
and perhaps it should. Does anyone know of a compiler that would not
evaluate the expressions left to right?

In C++11 it is baked in the draft C++11 standard in section 8.4.5 paragraph which says:

Within the initializer-list of a braced-init-list, the
initializer-clauses, including any that result from pack expansions
(14.5.3), are evaluated in the order in which they appear. That is,
every value computation and side effect associated with a given
initializer-clause is sequenced before every value computation and
side effect
associated with any initializer-clause that follows it in
the comma-separated list of the initializer-list.

I am sticking with C++11 going forward since it does not change the answer for the rest of the content, although the wording on sequencing does vary the conclusion is the same.

The second situation invokes undefined behavior since the order of evaluation of arguments to a function are unspecified and their evaluation is indeterminately sequenced with respect to one another. We can see this undefined behavior from section 1.9 paragraph 15 which says:

Except where noted, evaluations of operands of individual operators
and of subexpressions of individual expressions are unsequenced. [
Note: In an expression that is evaluated more than once during the
execution of a program, unsequenced and indeterminately sequenced
evaluations of its subexpressions need not be performed consistently
in different evaluations. —end note ] The value computations of the
operands of an operator are sequenced before the value computation of
the result of the operator. 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
.

and provides the following example:

f(i = -1, i = -1); // the behavior is undefined

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

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.

Multiple increment operators in single statement

The behavior here is undefined. See this question

Relevant standard quote:

§5/4.1 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.

The most common sequence point is the end of a statement.

Also worth noting from the standard:

§5.2.2/8 The order of evaluation of arguments is unspecified.

pre and post increment operations on a variable give different output on TC and gcc

C does not specify which order function arguments should be evaluated in, and so it is undefined and a compiler can do it however they choose, including arbitrarily and randomly. Bjarne Stroustrup says this explicitly in "The C++ Programming Language" 3rd edition section 6.2.2

He also gives a reason:

Better code can be generated in the absence of restrictions on expression evaluation order

Pre increment and post increment

 result = y++ + z-- + x++;
3 1 2 = 6

if you perform this again

 result1 = y++ + z-- + x++;
4 0 3 = 7

reason

operator++ returns the original value, before incrementing the variable.

and

++operator returns the incremented value

-- is same as above just its decrement



Related Topics



Leave a reply



Submit