3

In a for loop, because the last (update) expression cannot involve assignment, is it trivial whether it uses prefix or postfix increments/decrements? For example:

for (int i=0; i < 10; i++) {...}

vs.

for (int i=0; i < 10; ++i) {...}

Would there ever be a case where doing a prefix or postfix would matter in the update expression of a for loop?

samuelbrody1249
  • 4,379
  • 1
  • 15
  • 58
  • 1
    "*last (update) expression cannot involve assignment*" Why do you think it can't? – dxiv Jan 18 '21 at 04:52
  • @dxiv actually, I don't. I just have never seen it or used it, so perhaps I'm wrong with that... – samuelbrody1249 Jan 18 '21 at 04:53
  • 1
    @samuelbrody1249 `int n = -1; for(int i = 0; i < 10; n = i++);` – dxiv Jan 18 '21 at 04:55
  • 3
    `for (node *curr = head; curr != NULL; curr = curr->next) { … }` for processing a linked list. – Jonathan Leffler Jan 18 '21 at 04:56
  • 2
    In C, the compiler will treat the two identically — if it doesn't, you need a better compiler! In C++, since the prefix and postfix operators can be implemented separately for user-defined types, there are overheads associated with the postfix increment that are not present with the prefix operator. Consequently, in C++ it is usually better to use the prefix notation. – Jonathan Leffler Jan 18 '21 at 04:59
  • The TL;DR is: there is never a difference between i++ and ++i unless you mix them with other operators in the same expression. Which is why mixing i++ or ++i with other operators is bad practice. – Lundin Jan 18 '21 at 07:30

1 Answers1

7

It makes no difference. Prefix vs. postfix on the int loop variable produces identical assembly. I tested both loop forms on https://godbolt.org/ with a loop body that call printf("%d\n", i) on x86-64 gcc.

The prefix form for (int i=0; i < 10; ++i) {...} produces:

        mov     DWORD PTR [rbp-4], 0      ; Set i = 0.
.L3:
        cmp     DWORD PTR [rbp-4], 9      ; Compare i vs. 9.
        jg      .L4                       ; Exit the loop if i > 9.
        (... Loop body code ...)
        add     DWORD PTR [rbp-4], 1      ; Increment i.
        jmp     .L3                       ; Jump back o L3.
.L4:

The postfix form for (int i=0; i < 10; i++) {...} produces identical assembly (aside from a cosmetic difference in jump label names):

        mov     DWORD PTR [rbp-4], 0      ; Set i = 0.
.L7:
        cmp     DWORD PTR [rbp-4], 9      ; Compare i vs. 9.
        jg      .L8                       ; Exit the loop if i > 9.
        (... Loop body code ...)
        add     DWORD PTR [rbp-4], 1      ; Increment i.
        jmp     .L7                       ; Jump back to L7.
.L8:

And the result is the same even if I disable the optimizer (compile flag -O0). So it isn't the case that one form gets optimized into the other.

Pascal Getreuer
  • 2,906
  • 1
  • 5
  • 14