tags:

views:

644

answers:

13

Perhaps it doesn't matter to the compiler once it optimizes, but in C/C++, I see most people make a for loop in the form of:

for (i = 0; i < arr.length; i++)

where the incrementing is done with the post fix ++. I get the difference between the two forms. i++ returns the current value of i, but then adds 1 to i on the quiet. ++i first adds 1 to i, and returns the new value (being 1 more than i was).

I would think that i++ takes a little more work, since a previous value needs to be stored in addition to a next value: Push *(&i) to stack (or load to register); increment *(&i). Versus ++i: Increment *(&i); then use *(&i) as needed.

(I get that the "Increment *(&i)" operation may involve a register load, depending on CPU design. In which case, i++ would need either another register or a stack push.)

Anyway, at what point, and why, did i++ become more fashionable?


I'm inclined to believe azheglov: It's a pedagogic thing, and since most of us do C/C++ on a Window or *nix system where the compilers are of high quality, nobody gets hurt.

If you're using a low quality compiler or an interpreted environment, you may need to be sensitive to this. Certainly, if you're doing advanced C++ or device driver or embedded work, hopefully you're well seasoned enough for this to be not a big deal at all. (Do dogs have Buddah-nature? Who really needs to know?)

+1  A: 

Im my opinion it became more fashionable with the creation of C++ as C++ enables you to call ++ on non-trivial objects.

Ok, I elaborate: If you call i++ and i is a non-trivial object, then storing a copy containing the value of i before the increment will be more expensive than for say a pointer or an integer.

Peter G.
++ can be called on non-trivial objects as postfix or prefix manner, so i can't understand your answer.
Andrey
`++` as a prefix in C++ can modify the original object, whereas `++` as a postfix in C++ will have to make a copy of the original object to return as the value, if that value is used. All of this is irrelevant to C, the language about which the question was asked.
R..
I read C/C++ in the first sentence of the question.
Peter G.
not to mention that *creating* an object may also take considerable time.
Nathan Fellman
+9  A: 

It doesn't matter which you use. On some extremely obsolete machines, and in certain instances with C++, ++i is more efficient, but modern compilers don't store the result if it's not stored. As to when it became popular to postincriment in for loops, my copy of K&R 2nd edition uses i++ on page 65 (the first for loop I found while flipping through.)

Nathon
Since OP asked *when*, this question seems to be the definitive answer.
R..
Rich K
RBerteig
I guess I may as well share this, which shows a counter-intuitive result: http://physical-thought.blogspot.com/2008/11/pre-vs-post-increment-speed-test.html
Rich K
+3  A: 

For integer types the two forms should be equivalent when you don't use the value of the expression. This is no longer true in the C++ world with more complicated types, but is preserved in the language name.

I suspect that "i++" became more popular in the early days because that's the style used in the original K&R "The C Programming Language" book. You'd have to ask them why they chose that variant.

Darron
+1  A: 

At some level it's idiomatic C code. It's just the way things are usually done. If that's your big performance bottleneck you're likely working on a unique problem.

However, looking at my K&R The C Programming Language, 1st edition, the first instance I find of i in a loop (pp 38) does use ++i rather than i++.

Paul Rubel
Rich K
A: 

I think my predecessors are right regarding the side effects of choosing postincrement over preincrement.

For it's fashonability, it may be as simple as that you start all three expressions within the for statement the same repetitive way, something the human brain seems to lean towards to.

Mike
+5  A: 

For some reason, i++ became more idiomatic in C, even though it creates a needless copy. (I thought that was through K&R, but I see this debated in other answers.) But I don't think there's a performance difference in C, where it's only used on built-ins, for which the compiler can optimize away the copy operation.

It does make a difference in C++, however, where i might be a user-defined type for which operator++() is overloaded. The compiler might not be able to assert that the copy operation has no visible side-effects and might thus not be able to eliminate it.

sbi
It **does not** "create a needless copy. You're applying C++ thinking to C, which is simply not correct. There is no "copy" involved in evaluation of an expression with no side effects. Would you expect `i;` to take any time or generate any code? If not, why should `i++;` take more time or generate more code than `++i;`?
R..
If variable 'i' is volatile, the statement "i;" must generate code. On simple compilers which simply regard everything as volatile, the statement "i;" would still generate code. Note that if "i" is volatile, the statements "a=i++;" and "a=++i;" are both required to read "i" exactly once; on most architectures, neither could use a direct in-place increment.
supercat
I think VAXen had a pre-incriment-and-load opcode.
Nathon
@R..: I'm not sure what you're hammering at. The result of `i++` is the value of `i` before the increment. In order to return that result, `i` has to be copied somewhere. (It doesn't matter whether this could be done in hardware. The result still has to be stored somewhere.) If the result of the expression is discarded, compilers might eliminate this copying. I can't imagine a compiler not doing this if `i` is an `int`.
sbi
@sbi: And the value of `++i` is the value of `i` before the increment plus 1, and in order to return that result, the value of `i+1` has to be copied somewhere. The *side effect* of actually adding 1 to `i` does not have to be applied immediately. In the context of a loop control expression, a reasonably smart compiler will not bother to store the result of either form.
John Bode
@sbi: Your whole assumption is false. Yes, "in order to return that result", you need the value of `i` prior to the increment. But the code in question is not using that result, and as such, it **does not exist**. John's point that the side effect does not have to be applied immediately also stands.
R..
@supercat: No, there is no requirement in the C standard that `i;` generate code if `i` is `volatile`. If you claim there is, I'd like a citation. On an implementation that lacks asynchronous signals, `volatile` may be completely ignored by the compiler aside from issuing diagnostics about mismatched qualifiers on pointer types, as long as the code it generates around `setjmp` cannot lead to wrong local variable values being read after a `longjmp`.
R..
@R.: On the embedded-system compilers I've used, "volatile" forces memory reads to be performed exactly once, a behavior which is often absolutely essential if the 'volatile' variable is linked to the address of an I/O port. Much as I generally dislike such designs, on many I/O devices, reads "do things". For example, on many UARTS, if a data byte is available, a read will retrieve the data and delete it from the queue. Writing code for such devices in C would be impossible if the reads weren't guaranteed to happen precisely once each. Perhaps an implementation detail, but a common one.
supercat
@supercat: That's a common implementation-specific behavior, not part of the standard. I'm a bit confused what such implementations would do for expressions like `*x-*x` where `x` has type `volatile int *` and points to an I/O port that might return different values each time it's read...
R..
@R: Such an expression would arbitrarily yield either the first value read minus the second, or the second value minus the first. Useful code would need to have a sequence point. Note that if one didn't have a guarantee of volatile variables being read, one would have to go to bizarre lengths to read and ignore a port value.
supercat
A: 

I would add up to what other people told you that the main rule is: be consistent. Pick one, and do not use the other one unless it is a specific case.

Benoit
+1  A: 

My theory (why i++ is more fashionable) is that when people learn C (or C++) they eventually learn to code iterations like this:

while( *p++ ) {
    ...
}

Note that the post-fix form is important here (using the infix form would create a one-off type of bug).

When the time comes to write a for loop where ++i or i++ doesn't really matter, it may feel more natural to use the postfix form.

ADDED: What I wrote above applies to primitive types, really. When coding something with primitive types, you tend to do things quickly and do what comes naturally. That's the important caveat that I need to attach to my theory.

If ++ is an overloaded operator on a C++ class (the possibility Rich K. suggested in the comments) then of course you need to code loops involving such classes with extreme care as opposed to doing simple things that come naturally.

azheglov
@azheglov: I wonder if you've got it right, on why this is the reigning idiom. It seems right. I'm left to wonder on this, though: This bit of pedagogy may bite some junior coders on the rump. Both sbi and Peter G. point out the issue on operator++() overloading and computational cost.
Rich K
@Rick K: agreed. I thought about writing another paragraph about it and then skipped it for brevity. The compiler can optimize away the unneeded copy of an incremented integer, but a (deep?) copy of some class with an overloaded ++ operator - agreed, that's a different game.
azheglov
A: 

If the loop is too long, you need to reload the value in the cache to increment it before the jump to the begining. What you don't need with ++i, no cache move.

dzada
@dzada: Are you saying that ++i is more efficient than i++ in regards to the cache?
Rich K
-1 nonsense....
R..
I think what dzada means is that in while (i++) you may be incrementing i once too often.
reinierpost
Yes I say that for long loop, ++i can be more efficient in cache, it depends of architecture but it can't be less efficient. For exemple I work often with Sharks (tiger, Analog Device, DSP) and clearly that's better.
dzada
+2  A: 

Going a little further back than K&R, I looked at its predecessor: Kernighan's C tutorial (~1975). Here the first few while examples use ++n. But each and every for loop uses i++. So to answer your question: Almost right from the beginning i++ became more fashionable.

schot
+2  A: 

Because as soon as you start using "++i" people will be confused and curios. They will halt there everyday work and start googling for explanations. 12 minutes later they will enter stack overflow and create a question like this. And voila, your employer just spent yet another $10

Schildmeijer
+1 for incorporating the ridiculousness of incessantly asking this question into an actual answer!
R..
+2  A: 
Dave Jarvis
This is also the reason I was taught in college, i.e. i++ and --i are efficient stack operations on the PDP 11 - for details, see http://en.wikipedia.org/wiki/PDP-11_architecture#Stack_addressing_modes
reinierpost
@Dave Jarvis: Do you have a link to those quotes above? I tried to google them, no luck. I did find this though: http://cm.bell-labs.com/cm/cs/who/dmr/chist.html. According to that, ++ was an invention of Ken Thompson.
Rich K
@reinierpost: Thanks for the wiki link, an interesting read. See chist.html (full URL above): The PDP-7 ... did have a few 'auto-increment' memory cells, with the property that an indirect memory reference through them incremented the cell. This feature probably suggested such operators to Thompson; the generalization to make them both prefix and postfix was his own. Indeed, the auto-increment cells were not used directly in implementation of the operators, and a stronger motivation for the innovation was probably his observation that the translation of ++x was smaller than that of x=x+1.
Rich K
@Rich: I do not have a link to the quotes: they are from my inbox.
Dave Jarvis
A: 

In C, all operators that result in a variable having a new value besides prefix inc/dec modify the left hand variable (i=2, i+=5, etc). So in situations where ++i and i++ can be interchanged, many people are more comfortable with i++ because the operator is on the right hand side, modifying the left hand variable

Please tell me if that first sentence is incorrect, I'm not an expert with C.

Wallacoloo