Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
Solved

# increment and decrement operators usage problem

Posted on 2006-05-03
Medium Priority
328 Views
Dear All,

I am facing a problem while using the following C expression in a program.

int x=0;

x=++x + x++ + x-- + --x;

printf("x = %d\n",x);

I got the x value was 3. But I could not understand it.
Could any one explain me?

Thanks and Regards,
Srinivas G
0
Question by:srinivasganji
• 10
• 9
• 4
• +4

LVL 53

Accepted Solution

Infinity08 earned 2000 total points
ID: 16596064
First of all, this is very ambiguous C code, as the order in which the pre-in/decrement (and post-in/decrement) operators are executed is not defined, and can be any order.

In any case, here we leave at the post-in/decrement operators for clarity :

x = ++x + x + x + --x;

So, we're left with this, which becomes :

int y = ++x; /* y now contains 1, x also contains 1 */
y += x; /* y now contains 2, x still contains 1 */
y += x; /* y now contains 3, x still contains 1 */
y += --x; /* y now contains 3, x contains 0 */
x = y; /* x contains 3 */

And finally the post-in/decrement operators :

x += 1;
x -= 1;

will leave x at 3.
0

LVL 24

Expert Comment

ID: 16596541
this code is not ambigous it's broken. Whatever happens is fine if the result is 0, 1, 1000 launch of  rocket or whatever. The code invokes undefined behaviour. So you arguments are invalid infinity08, and false.

What is right is the solution you  wrote down with int y = ...

This is fully specified and works, but that is not a point fo the broken code the OP posted originally.

The information gathering that are called "sequence points" and can be found in the Annex C of the C Standard.

Regards
Friedrich

0

LVL 53

Expert Comment

ID: 16596690
>> Whatever happens is fine if the result is 0, 1, 1000 launch of  rocket or whatever.
>> The code invokes undefined behaviour.
If ambiguous doesn't mean just that, then excuse me for not being native english :)
The dictionary says "open to two or more interpretations; or of uncertain nature or significance" ... I don't see the difference with "whatever happens is fine; the behaviour is undefined". Anyway, I don't feel like getting into a linguistic discussion, because as i said ... I'm not native english, so I'm probably wrong ... my apologies.

Can I ask you what you mean by "broken" ? It does compile (why wouldn't it) ...

The breakdown of the code i gave in my earlier post, is how the compiler treated this particular line of code to arrive at 3.
0

LVL 46

Expert Comment

ID: 16597263
Hi srinivasganji,

What the other guys are trying to say is that the C standard doesn't prohibit this kind of expression, it doesn't define it either.  What you see happening with your current compiler may be different from what happens with a different compiler because the implementation is left up to the individual vendors.

The underlying problems is that you are using inline increment/decrement operators along with other operations on the same variable and exactly WHEN the effects are applied is unknown.  ++x says that when the statement is complete x will be incremented by one.  It does NOT say that x will be incremented for the remainder of the expression, nor does it prohibit it from being incremented.

These are fun exercises, but it's best to stay away from this kind of code in "real life".

Good Luck!
Kent
0

LVL 85

Expert Comment

ID: 16597790
The standard says

Between the previous and next sequence point an object shall have its stored value
modified at most once by the evaluation of an expression. Furthermore, the prior value
shall be read only to determine the value to be stored.

Note the word "shall"

In this International Standard, â€˜â€˜shallâ€™â€™ is to be interpreted as a requirement on an
implementation or on a program; conversely, â€˜â€˜shall notâ€™â€™ is to be interpreted as a
prohibition.
0

LVL 46

Expert Comment

ID: 16597824
Hi ozo,

Agreed.

The issue is what happens during the evaluation of the expression.  Is the memory value used or the register value?  It would appear that a lot of the answer is simply the underlying instruction set.

Kent
0

LVL 85

Expert Comment

ID: 16597949
Quoting from the standard again

1 undefined behavior
behavior, upon use of a nonportable or erroneous program construct or of erroneous data,
for which this International Standard imposes no requirements
2 NOTE Possible undefined behavior ranges from ignoring the situation completely with unpredictable
results, to behaving during translation or program execution in a documented manner characteristic of the
environment (with or without the issuance of a diagnostic message), to terminating a translation or
execution (with the issuance of a diagnostic message).
3 EXAMPLE An example of undefined behavior is the behavior on integer overflow.

So anything at all can happen.  As fridom says, the result can be 0, 1, 1000 launch of  rocket or whatever.
0

Expert Comment

ID: 16600199
so kent, what is it you are actually attempting to accomplish with the value of X?
0

LVL 24

Expert Comment

ID: 16602890
you can not have more broken code than undefined behaviour.  One can not argue about it one can not reason about it the only thing one can do is avoiding it. If you don't you program is garbage.

Regards
Friedrich
0

LVL 53

Expert Comment

ID: 16603200
Yes, fridom, but I don't think srinivasganji was asking this question to actually USE that particular line of code ... he just wants to understand why it gives 3 as a result. Didn't we all when we first saw code like that ?
0

LVL 5

Expert Comment

ID: 16603624
Hi,

I used Turbo C++ compiler and it gave me answer 0. However if you use a stack to calculate the value or evaluate the expression from right to left , you will get a different value.

Regards,
Siddhesh
0

LVL 53

Expert Comment

ID: 16603643
Apparently Turbo C++ compiler did both pre-in/decrement before starting the actual calculations, ie. :

x += 1;
x -= 1;
x = x + x + x + x;
x += 1;
x -= 1;

Which gives 0 ... this only proves that each compiler interpretes how to handle multiple in/decrements in his own way.
0

LVL 5

Expert Comment

ID: 16603701
Hi,

Yes, the increment operators are pretty simple in operations but in a experssion they behave differently.

check the output of

x = 0
printf("%d\t%d\t%d\t%d\t%d\n",x,++x,x++,x--,--x);

it turns out as...

0      0       -2      -1      -1

Here the printf function call is actually filling up the parameter values in place of %d , however since function parameters are always loaded onto a STACK from right to left, even if the eventual value of x=0 due to the increment decrement operators.

The compiler supplys the 'then' values of the variable x when evaluating from right to left.

So in the above statement...if we see from the right side --x is calculated first and so we get -1  , the next is x-- which provides the value -1 again to the 2nd parameter to printf and further decrements the value and makes it -2... the next operation is x++ , so again here as in the previous case it assigns the value to the printf argument and increments the value of x, making it -1 and now in the next operation ++x, the value of x is increased from -1 to 0 and then it is assigned in to the printf parameter.

All this happens because the STACK comes into play..the compiler keeps on pushing the value of the variable onto the stack as a value and doesn't push the actual variable onto the stack.

However while evaluating expressions as in ..

x = ++x + x + x + --x;

the compiler might be pushing actual variable 'x' onto the stack and evaluating so that's why we get the value 0.

Tried to put in the best way i could.

Regards,
Siddhesh
0

LVL 24

Expert Comment

ID: 16604010
to infinity08
No I did not have looked further and as posted it does not matter what you "think" happens or what happens with your compiler. The results are unspecified, everything is find and that's it.

So all reasoning is wrong and simply false.

Friedrich
0

LVL 53

Expert Comment

ID: 16604427
>> So all reasoning is wrong and simply false.
Depends what we're reasoning on ... you're reasoning on the specifications only ... I'm reasoning in the environment srinivasganji used to get this result, as well as on the specifications.

Based on the specifications, it should be noted that the specifications don't define what should happen (as i did).
But the compiler still did something or it wouldn't have come up with a result. Hence the second part of my post, explaining how the compiler implemented this undefined behaviour.

So, in my humble opinion, it DOES matter what happens in this specific compiler, especially since that was exactly the question that was asked ...
0

LVL 24

Expert Comment

ID: 16604546
This is ridicoulus and I'm not willing to spend more time on it. That this compiler works that way has no meaning.  It's sheer luck with different optimazations the result may or may not be different. So whatver the OP thinks about it it's broken. DOT.
Friedrich
0

LVL 53

Expert Comment

ID: 16604610
OK, let's let srinivasganji decide what he wanted to know :)
0

LVL 24

Expert Comment

ID: 16605384
My last post on it. It may or may not that your arguments are valid.

it could be that this
x=++x + x++ + x-- + --x;

is simply reduced to
x = 3

it could be x= 10 and what would be fine also.

You can not argue about how things work if the invoke undefine behaviour.

Friedrich
0

LVL 53

Expert Comment

ID: 16605770
Knowledge of the inner workings of a compiler (in general) and the compiler used (specifically), DOES allow you to say what the compiler did. Even though it's not defined in the specification, it's still defined by the compiler. That's been my whole point in this discussion (but apparently you missed that).

Compilers don't follow the specification to the letter - they fill in the undefined parts as they want it.

The compiler i use atm, is the MingW compiler (GCC port to Windows32), and it handles this code exactly the way i wrote down in my first post. The reasoning behind it is that pre-increments are done just prior to the moment where the variable is referenced, not prior to the whole assignment (as it was apparently done in Turbo C++). So, using the statement in question on the MinGW compiler version I'm using will always yield 3. And it IS defined for the compiler, and there IS a logic behind it. And it's NOT against the specifications at all (since they don't specify how it should be handled).

The reason you shouldn't use this kind of code is because it's not portable at all. But it's still worth it to discuss it, as it teaches you how your compiler works, while it also reminds you why you whould avoid this code.
0

LVL 22

Expert Comment

ID: 16609372
You're basically running with scissors blindfolded if your C code makes use of undefined behavior.  Here's some good coverage of Undefined Behavior:  http://c2.com/cgi/wiki?UndefinedBehavior

You might be interested to know that "x = ++x + x++ + x-- + --x;" is actually unambiguous in Java.  Java explicitly requires that the side effects on the left side of a binary operator must take effect before the right side is evaluated.

That expression would get broken down by the Java compiler like this:
x = 0;
x = x + 1;  // ++x, x = 1 now
int sum = x; // starting term of sum, ++x, sum = 1
sum = sum + x;  // adding value of x++ to the sum, sum = 2
x = x + 1; // x++ side effect, now x = 2
sum = sum + x;  // adding value of x--, so sum = 4
x = x - 1 ; // x-- side effect, x = 1
x = x - 1; // --x side effect, x = 0
sum = sum + x; // adding in --x, now sum = 4
x = sum; // doing final assignment

So, in Java, that expression winds up assigning 4 to x.
0

LVL 24

Expert Comment

ID: 16795981
What? An explanation of undefined behaviour should be the answer?

This can't be meant serious.

Friedrich
0

LVL 85

Expert Comment

ID: 16796027
printf("%d\t%d\t%d\t%d\t%d\n",x,++x,x++,x--,--x);
also modifies the stored value of an object more than once between sequence points, and so is also invalid code with undefined behavior.
0

LVL 24

Expert Comment

ID: 16796097
Yes, so what does it have to do with the answer to this question?

Regards
Friedrich
0

LVL 53

Expert Comment

ID: 16796115
>> What? An explanation of undefined behaviour should be the answer?
I'm not gonna have this discussion with you again ... I suggest you read this whole thread once more, and especially my last post ... it explains my point of view, and the validity of my first reply as an answer to srinivasganji's question.
0

LVL 85

Expert Comment

ID: 16796159
Nothing, other than that they are both undefined.
But for the record I thought the misleading statement in http:#16603701 that
"function parameters are always loaded onto a STACK from right to left, even if the eventual value of x=0 due to the increment decrement operators."
ought to be corrected.
There is no guarantee that function parameters are always loaded onto a STACK from right to left,
and there is no guarantee that the eventual value of x would be 0, since the violation of a shall clause is prohibited.
0

LVL 24

Expert Comment

ID: 16796206
Yes, so what does it have to do with the answer to this question?

Regards
Friedrich
0

LVL 24

Expert Comment

ID: 16797206
Well infinity08 if you can't see that your tip is just working by happening, then I'm sorry for you. I suggest you post you answer in some C forum and see the results. However accepting such an explanation as an answer just makes the experts in "experts-exchange" a bad joke.

This expert tip from you is just a bad programmers tip, That's harsh but unfortunatly true.

If we start on accepiting solutions based on unspecified behaviour this forum should be renamed to.
Messing around with C.

Friedrich
0

LVL 53

Expert Comment

ID: 16797255
Some notes :

1) I DID state that the behaviour was unspecified
2) The question was to explain why he got 3 as a result with that code ... that's what I did : I explained why HIS COMPILER gave 3 as a result for that code
3) As far as I understood, that code was not to be used in any real code ... it was just meant to understand some basic concepts of C and the compiler.

So, any and all of your arguments against my answer are invalid ... if YOU can't see that, then maybe you're being a bit pedantic, and maybe you can't accept that a different approach to a question isn't necessarily a bad approach. I apologise for becoming personal, but I hope you realise you started that ...

And again you tricked me in having the same discussion all over ...
0

LVL 53

Expert Comment

ID: 16797277
One final comment ... I'm starting to realise that this comment of yours :

>> One can not argue about it one can not reason about it the only thing one can do is avoiding it.

applies more to you, than to the code. Same apology as before applies ...
0

## Featured Post

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This tutorial is posted by Aaron Wojnowski, administrator at SDKExpert.net.  To view more iPhone tutorials, visit www.sdkexpert.net. This is a very simple tutorial on finding the user's current location easily. In this tutorial, you will learn hoâ€¦
Examines three attack vectors, specifically, the different types of malware used in malicious attacks, web application attacks, and finally, network based attacks.  Concludes by examining the means of securing and protecting critical systems and infâ€¦
The goal of this video is to provide viewers with basic examples to understand and use structures in the C programming language.
The goal of this video is to provide viewers with basic examples to understand how to create, access, and change arrays in the C programming language.
###### Suggested Courses
Course of the Month11 days, left to enroll