Difference between i = ++i and ++i [duplicate]
Asked Answered
A

6

8

Possible Duplicate:
Could anyone explain these undefined behaviors (i = i++ + ++i , i = i++, etc…)

What is the difference between i = ++i; and ++i; where i is an integer with value 10?

According to me both do the same job of incrementing i i.e after completion of both the expressions i =11.

Alysiaalyson answered 12/10, 2010 at 11:49 Comment(1)
Duplicate? #2903138Corbet
E
10

i = ++i; invokes Undefined Behaviour whereas ++i; does not.

C++03 [Section 5/4] says 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.

In i = ++i i is being modified twice[pre-increment and assignment] without any intervening sequence point so the behaviour is Undefined in C as well as in C++.

However i = ++i is well defined in C++0x :)

Exterritorial answered 12/10, 2010 at 11:50 Comment(41)
Predence has nothing to do with the order of evaluation. i = ++i invokes UB because i is being modified more than once between two sequence points.Exterritorial
Can you cite authoritative sources on this? Certainly i = i++ has undefined behavior: because it's not defined whether the value of i++ will be copied into i before or after i is incremented. But it's less clear to me that i = ++i has order-dependent results. It's plausible but not obvious to me.Guelders
@Prasoon Saurav - Most, maybe all, compilers follow the precedence rule and evaluate it to a logical value. I do realize you are quoting from cppreference.com/wiki/operator_precedenceDambrosio
If i were an iterator it would actually be defined because it would become i.operator=(i.operator++()) and there is a guaranteed sequence point here, i.e. the arguments are evaluated before the function. When i is an integer or pointer then it is indeed undefined as there are no such guarantees.Mckinnie
@Steve: ok, that makes sense, it just seems intuitive that since ++i returns (original value of i + 1) as if i had already been incremented, therefore the increment to i must happen before the value of ++i is returned. But I guess that's not what the standard says.Guelders
@Prasoon: thanks. I guess the missing piece here for me, and probably for the OP, is how sequence points relate to the expression in question.Guelders
@Prasoon Saurav - Compilers generally do not always strictly follow the rules laid down by the specifications, as both continue evolve. So what you read on the specifications, may surprise you on the compiler.Dambrosio
@DumbCoder: no, it is not a "suprise" if the standard says that something is undefined behavior, and the compiler does something that you consider sensible. Undefined behavior means that the compiler can do anything. Even if it does what you want, it is still strictly following the standard.Protoxylem
@Steve Jessop - Undefined behaviour, then why does the code gives the same output even after 50 runs. The specs mention undefined, but the compiler is strictly following the precedence rule and evaluating to the same result always. Isn't that someting which seems to be following the same evaluation path always.Dambrosio
@Dambrosio : Now try your experiment on 100 different compilers. Undefined means anything can happen which also includes the result as per your expectation.Exterritorial
@DumbCoder: Undefined behaviour means that the implementation is allowed do anything. Doing the same thing every time qualifies as a kind of "anything". Undefined behaviour does not mean, "the implementation is required by the standard to do something weird". It means what it says - the standard does not define the behaviour.Protoxylem
@DumbCoder: undefined behavior means that the compiler can do as it likes. Often, that just means that the compiler vendors didn't write a specific code path for it, so it just "falls through the cracks", getting parsed according to some arbitrary quirk of their parser, and then has code generated for it which just so happens to work out some specific way. And yes, in practice that might be deterministic for a specific version of a specific compiler, but different compilers will handle it differently, because they're structured differently, so it ends up being handled by a different rule.Statement
One of the ways in which this might fail is through optimizations. Because the standard states that there may be only one write to a variable between sequence points, the compiler can assume that this is the case, and optimize around this assumption. And then your code will break if it violates that assumption, even if the code seems deterministic otherwise.Statement
@Prasoon Saurav - Could you mention the names of 100 compilers you specified ? Rather than harping around without a concrete reason, don't mention the specifications at the drop of a hat, if you don't understand what it says. @Jalf & @ Steve - Would take your point on this.Dambrosio
@Dambrosio : Why would someone possibly test and predict the behaviour which has already been mandated by the Standard as Undefined. That certainly means you don't understand what Undefined Behaviour means, do you?Exterritorial
@Dumbcoder : We are talking about Standard C[C++] here and certainly not concerned with how implementations gives one or different output. Ok if you don't understand what Undefined Behaviour means this is for you behavior, such as might arise upon use of an erroneous program construct or erroneous data, for which this International Standard imposes no requirementsExterritorial
@Prasoon Saurav - Possibly you don't seem to read what are in the comments also. Did you see what jalf or Steve said ? Did mentioning that ever cross you head, that is if you know ? And when you say undefined, you only mention specs, did you mention why the compiler was doing the behaviour it was ? Probably next time explain both ways rather than copy psting the specs. And you still haven't mentioned the 100 compilers ? Coming up with figures seems so easy, it seems.Dambrosio
@Dumbcoder : I have read and understood what @jalf and @steve said in their comments but being a DumbCoder you just don't seem/want to understand what I have said.Exterritorial
@Prasoon Saurav - Probably you don't have the urge or capability to explain what you want to say ?Dambrosio
@DumbCoder: "why the compiler was doing the behaviour it was?" is a pointless question if we're talking about UB.Haiti
Why is it well defined in C++0XMedlock
@Martin York : Sorry messed up a bit. It is Undefined in C++0x too. Read this thread and Johannes Schaub's answer here.Exterritorial
@CashCow: Correct in that there is a sequence point in there but wrong reason. There is a sequence point after a function call has been completed not after parameter evaluation.Medlock
@DumbCoder: @LarsH: Read this: #368133Medlock
@Steve Jessop: Oops. Re-writing that.Medlock
@DumbCoder: On some of the more esoteric rules the conformance may vary slightly but is always well documented. But on these the most basic and heavily used parts of the standard (like expression evaluation) there is not a compiler that is NOT 100% in compliance. If a compiler was not 100% in compliance then so much code would break that the compiler would quickly be dumped and considered broken.Medlock
@Prasoon Saurav - No point downvoting all my answers just because I questioned your incomplete answers ? Should be open for discussion rather than taking revenge just because you cannot provide complete answers.Dambrosio
@DumbCoder: I have no idea what you are talking about bro. I have stopped downvoting long back. The number of downvotes given by me is just 5 and downvoting without any reason doesn't make sense.Exterritorial
@Dambrosio : I have no idea what you want to say because the answer given by me is complete IMHO. As @Charles said your question/comment to my answer was completely useless[my opinion] and pointless. I have had such pointless and idiotic discussions with guys like you several times and I don't see any point in making you understand what I wanted to say. See ya.Exterritorial
@Prasoon Saurav - I checked out your downvotes yesterday 2 and today 5. I expected this behaviour from you, so I checked out your downvotes yesterday itself. Just because somebody says it is final, it isn't final. And idiotic discussions, regarding that I am not sure questioning an incomplete answer is idiotic or giving incomplete and incomprehensive reasoning, as yours, is idiotic.Dambrosio
@Dambrosio : If you think you are the only one who has got so many downvotes one after the other have a look at this thread. Please think twice before blaming someone unnecessarily.Exterritorial
@Dambrosio : Oh really did you check my downvotes, huh? I have no reason to prove anything to you. Think whatever you think but I am not a jerk who just loves downvoting.Exterritorial
@Dambrosio : As I have already said explaining Undefined Behaviour is insane IMO but I won't stop you from doing anything and no further comments from my side. If you want to know who downvoted your answers ask Jeff and co. but just don't irritate me.Exterritorial
@Prasoon both answers you link to state that i = ++i is well-defined in C++0x, and I gave references to the defect report that reasoned about the behavior.Withershins
@Martin please read the linked answer of me, which shows that it is valid in C++0x.Withershins
@CashCow, that's not correct in general. int *p = ...; is an iterator. Still p = ++p; is undefined behavior in C++03.Withershins
@Johannes : I was talking about your deleted answer here in which you diagrammatically showed that i = ++i is UB in C++0x. You had written that This shows how the value computation on i is unsequenced relative to the increment side effect on i, thus behavior is undefined. Exterritorial
@Prasoon yep, I was interpreting the Standard wrongly. All things that people say about C++, including myself, is wrong, basically. You need to make your own interpretation to be real good at it. Otherwise you are just repeating the misinterpretations that me, James, Stroustrup or anyone else does. Anyone is human, after all.Withershins
@Johannes : Yeah true. Read #637 again. i = ++i should be well defined in C++0x. I don't know whether these things have real practical applications or not. Once we know something like i = i++ is UB we don't use it anyway.Exterritorial
@Prasoon Saurav - I am not irritating, but you are. Why are you replying back again and again, when I am not asking anything ?Dambrosio
@Johannes_Schaub I mentioned the case of a pointer. Although a pointer can be used as an iterator I was of course referring to an iterator implemented as a class.Mckinnie
E
7

Writing i = ++i; writes to variable i twice (one for the increment, one for the assignment) without a sequence point between the two. This, according to the C language standard causes undefined behavior.

This means the compiler is free to implement i = ++i as identical to i = i + 1, as i = i + 2 (this actually makes sense in certain pipeline- and cache-related circumstances), or as format C:\ (silly, but technically allowed by the standard).

Electrostriction answered 12/10, 2010 at 11:56 Comment(2)
+1 for mentioning sequence points, something that is very useful to be aware of!Emit
+1 for giving a link to description of sequence points.Guelders
O
3

i = ++i will often, but not necessarily, give the result of

i = i;

i +1;

which gives i = 10

As pointed out by the comments, this is undefined behaviour and should never be relied on

while ++i will ALWAYS give

i = i+1;

which gives i = 11;

And is therefore the correct way of doing it

Outherod answered 12/10, 2010 at 11:56 Comment(4)
If you downvote me, then atleast have the courtesy of telling what was wrong with my postOutherod
I didn't downvote you, but it might be because your answer is imprecise, saying that it will "often, but not necessarily" give a certain result. It is officially undefined behavior, and trying to guess the odds of which outcome you're going to get might just give a reader the wrong idea, that it is somehow possible to rely on the result.Statement
@jalf - I can't see anything wrong with kskjon's answer. It's not maximally precise but it's totally accurate, and it answers the OP's question. kskjon makes it clear that the i=10 result will "not necessarily" happen. I don't see how that can give a reader an inaccurate idea that it is somehow possible to rely on that result.Guelders
@LarsH: Like I said, I didn't downvote it, and you're right, there's nothing factually wrong with his answer. But it does give the impression that you can "usually" rely on a specific answer. Or specifically, by not mentioning that the behavior is actually entirely undefined, it might lead the reader to believe that the behavior is somewhat constrained, that you can still rely on it to do something sane, or that it might behave in one of a set number of ways. I'd be happy if he edited it to include a note that the former is undefined. And if I had to guess, that's why it was downvotedStatement
C
2

If i is of scalar type, then i = ++i is UB, and ++i is equivalent to i+=1. if i is of class type and there's an operator++ overloaded for that class then i = ++i is equivalent to i.operator=(operator++(i)), which is NOT UB, and ++i just executes the ++ operator, with whichever semantics you put in it.

Ciro answered 12/10, 2010 at 12:1 Comment(0)
H
1

The result for the first one is undefined.

Haiti answered 12/10, 2010 at 11:51 Comment(2)
If and only if ++ is the biult-in ++operator. If it is overloded, then it is NOT undefined behaviorCiro
@Armen: that's what I was going to say on Prasoon's answer, then I noticed that the questioner said i was an "integer". I think it's reasonable to assume that this means an integer type, hence UB.Protoxylem
A
1

These expressions are related to sequence points and, the most importantly, the first one results in undefined behavior.

Await answered 12/10, 2010 at 11:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.