As for any other obscure mechanism in C, there are various historical reasons for it. In ancient times, when dinosaurs walked the earth, compilers would make more efficient code from i++ than i+=1 . In some cases, compilers will generate less efficient code for i++ than for ++i , because i++ needs to be saved for further increase. Unless you have a dinosaur compiler, none of this matters in terms of efficiency.
As with any other obscure mechanism in C, if it exists, people will start using it. I will use the generic *p++ expression as an example (this means: p is a pointer, take the contents of p , use this as the result of the expression, and then increase the pointer). He must use a postfix and never a prefix, otherwise it will mean something completely different.
Some dinosaurs once began to write unnecessary complex expressions, such as *p++ , and because they did this, it became commonplace, and today we consider such code as something trivial. Not because it is, but because we are so used to reading it.
But in modern programming, there is absolutely no reason to write *p++ . For example, if we look at the implementation of the memcpy function, which has these premises:
void* memcpy (void* restrict s1, const void* restrict s2, size_t n) { uint8_t* p1 = (uint8_t*)s1; const uint8_t* p2 = (const uint8_t*)s2;
Then one of the popular ways to implement actual copying is:
while(n--) { *p1++ = *p2++; }
Now, some people will rejoice because we used so few lines of code. But a few lines of code are not necessarily a measure of good code. This is often the opposite: consider replacing it with a single line while(n--)*p1++=*p2++; , and you understand why this is true.
I donโt think any case is very readable, you have to be an experienced C programmer to understand it without scratching your head for five minutes. And you can write the same code like this:
while(n != 0) { *p1 = *p2; p1++; p2++; n--; }
For longer, and most importantly, it gives exactly the same machine code as the first example.
Now let's see what happened: because we decided not to write obscure code with a large number of operands in one expression, we could also use ++p1 and ++p2 . This will give the same machine code. The prefix or postfix does not matter. But in the first example with obscure code *++p1 = *++p2 completely change the meaning.
Summarizing:
- There are prefix and postfix increment operators for historical reasons.
- In modern programming, the presence of two different such operators is completely unnecessary, unless you write obscure code with several operators in one expression.
- If you write obscure code, you will find ways to motivate the use of both a prefix and a postfix. However, all such code can always be rewritten.
You can use this as a measure of the quality of your code: if you ever find yourself a code where it is important whether you use a prefix or postfix, you write bad code. Stop it, rewrite the code.