Javed Akram
Javed Akram

Reputation: 15354

Is (--i == i++) an Undefined Behavior?

this question is related to my previous problem. The answer I got was "It is an Undefined behavior."

Please anyone explain:

Example code:

int i = 5;
if (--i == i++)         
   Console.WriteLine("equal and i=" + i);           
else
   Console.WriteLine("not equal and i=" + i);

//output: equal and i=6

Upvotes: 0

Views: 1373

Answers (8)

Guffa
Guffa

Reputation: 700650

In C the result is undefined, in C# it's defined.

In C, the comparison is interpreted as:

Do all of these, in any order:
- Decrease i, then get value of i into x
- Get value of i into y, then increase i
Then compare x and y.

In C# there are more operation boundaries, so the comparison is interpreted as:

Decrease i
then get value of i into x
then get value of i into y
then increase i
then compare x and y.

It's up to the compiler to choose in which order the operations are done within an operation boundary, so putting contradictory operations within the same boundary causes the result to be undefined.

Upvotes: 1

usul
usul

Reputation: 804

(This assumes C or C++.)

Carl's answer is exact in general.

In specific, the problem is what Jeremiah pointed out: sequence points.

To clarify, the chunk of code (--i == ++i) is a single "happening". It's a chunk of code that's evaluated all at once. There is no defined order of what happens first. The left side could be evaluated first, or the right side could, or maybe the equality is compared, then i is incremented, then decremented. Each of these behaviors could cause this expression to have different results. It's "undefined" what will happen here. You don't know what the answer will be.

Compare this to the statement i = i+1; Here, the right side is always evaluated first, then its result is stored into i. This is well-defined. There's no ambiguity.

Hope that helps a little.

Upvotes: 1

Matthew Flaschen
Matthew Flaschen

Reputation: 284927

It's undefined in C, but well-defined in C#:

From C# (ECMA-334) specification "Operator precedence and associativity" section (§14.2.1):

  • Except for the assignment operators and the null coalescing operator, all binary operators are left- associative, meaning that operations are performed from left to right. [Example: x + y + z is evaluated as (x + y) + z. end example]

So --i is evaluated first, changing i to 4 and evaluating to 4. Then i++ is evaluating, changing i to 5, but evaluating to 4.

Upvotes: 2

Stephen Chung
Stephen Chung

Reputation: 14605

Undefined behavior == the result cannot be guaranteed to always be the same whenever you run it in the exact same conditions, or the result cannot be guaranteed to always be the same whenever you use different compilers or runtimes to execute it.

In your code, since it is using a equal comparison operator which does not specify which side of the operands should be executed first, --i or i++ may end up running first, and your answer will depend on the actual implementation of the compiler. If --i is executed first, it will be 4 == 4, i=5; if i++ is implemented first, it will be 5 == 5, i=5.

The fact that the answer may turn out to be the same does not prevent the compiler from warning you that this is an undefined operation.

Now if this is a language that defines that the left hand side (or right hand side) should always be executed first, then the behavior will no longer be undefined.

Upvotes: 0

Jerry Coffin
Jerry Coffin

Reputation: 490438

Your previous question was tagged [C], so I'm answering based on C, even though the code in your current question doesn't look like C.

The definition of undefined behavior in C99 says (§3.4.3):
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).

Appendix J.2 of the C standard has a (long -- several pages) list of undefined behavior, though even that still isn't exhaustive. For the most part, undefined behavior means you broke the rules, so the way to know it is to know the rules.

Upvotes: 0

vz0
vz0

Reputation: 32923

Because the C standard states so. And your example clearly shows an undefined behabiour.

Depending on the order of evaluation, the comparison should be 4 == 5 or 5 == 6. And yet the condition returns True.

Upvotes: 0

Jeremiah Willcock
Jeremiah Willcock

Reputation: 30989

Yes, that expression is undefined behavior as well (in C and C++). See http://en.wikipedia.org/wiki/Sequence_point for some information on the rules; you can also search for "sequence point" more generally (that is the set of rules that your code violates).

Upvotes: 1

Carl Norum
Carl Norum

Reputation: 225092

What is an Undefined-Behaviour?

It's quite simply any behaviour that is not specifically defined by the appropriate language specification. Some specs will list certain things as explicitly undefined, but really anything that's not described as being defined is undefined.

how can I know my code has an undefined behavior?

Hopefully your compiler will warn you - if that's not the case, you need to read the language specification and learn about all the funny corner cases and nooks & crannies that cause these sorts of problems.

Be careful out there!

Upvotes: 2

Related Questions