Some of this answer is based on my experience rather than on any hard facts, so please take it with a grain of salt.
Reasons for i++ as the default loop incrementor
Postfix vs Prefix
The postfix incrementor i++ produces a temporary pre-incremented value that's passed 'upwards' in the expression, then variable i is subsequently incremented.
The prefix incrementor ++i does not produce a temporary object, but directly increments i and passes the incremented result to the expression.
Performance
Looking at two simple loops, one using i++, and the other ++i, let us examine the generated assembly
#include <stdio.h>
int main()
{
for (int i = 0; i < 5; i++) {
//
}
for (int j = 0; j < 5; ++j) {
//
}
return 0;
}
Generates the following assembly using GCC:
main:
push rbp
mov rbp, rsp
mov DWORD PTR [rbp-4], 0
.L3:
cmp DWORD PTR [rbp-4], 4
jg .L2
add DWORD PTR [rbp-4], 1
jmp .L3
.L2:
mov DWORD PTR [rbp-8], 0
.L5:
cmp DWORD PTR [rbp-8], 4
jg .L4
add DWORD PTR [rbp-8], 1
jmp .L5
.L4:
mov eax, 0
pop rbp
ret
.L3 corresponds to the first loop, and .L5 corresponds to the second loop. The compiler optimizes away any differences in this case resulting in identical code, so no performance difference.
Appearance
Looking at the following three loops, which one appeals to you most aesthetically?
for (int i = 0; i < 5; i++) {
//
}
for (int i = 0; i < 5; ++i) {
//
}
for (int i = 0; i < 5; i+=1) {
//
}
For me i+=1 is right out, and ++i just feels sort of... backwards
Ergonomics
- i++) - Your hand is already in the correct position to type ) after typing ++
- ++i) - Requires moving from upper row to homerow and back
History
Older C programmers, and current C programmers who write systems level code make frequent use of i++ to allow for writing very compact code such as:
// print some char * s
while(*s)
putc(*s++);
// strcpy from src to dest
while (*dest++=*src++);
Because of this i++ became the incrementor C programmers reach for first, eventually becoming a sort of standard in cases where ++i vs i++ have the same functionally.