The One-Line Trick for Iterating Backwards in C That Almost Everyone Gets Wrong

A size_t index counting down to zero looks obvious but breaks: i >= 0 is always true, and an empty buffer wraps i to SIZE_MAX. Switching to ssize_t works but drags in signed-conversion traps, a POSIX-only type, and promotion issues on 32-bit. The clean fix is `for(size_t i = count; i--; )`, relying on post-decrement and well-defined unsigned wraparound to keep i in bounds.

So much simpler! Let's break it down: The key is the postdecrement operator on i.
  1. kenferry

    I know it's "too clever", but if I'm writing code no one else will ever see,

    while (i --> 0) {

    // use array[i]

    }

    easy to read (if not understand), and correct!

  2. Joker_vD

    That's the price of innovation, I guess; before C invented its "for"-loop, other languages had their equivalents generally looking like this:

    FOR var = start [DOWN] TO end BY step DO ... END

    No custom increment expressions, and "step" even usually was only allowed to be a constant (in which case, the language usually didn't have DOWN specifier and used the step's sign instead). Then Dennis Ritchie invented C, and ditched the traditional "do"-loop (Fortran started that construct with DO, so it was called DO loop; Algol used FOR instead, but most people preferred the Fortran's nomenclature... until C came to dominate, but that wouldn't happen for yet another 20 years) in favour of his invention because he felt that easily iterating through linked lists or strings was a much more pressing concern:

    for(p=head; p; p=p->next) { ... }

    for(s=str; *s; s++) { ... }

    The downside, of course, is that now you can't straightforwardly write

    for size_t i = count - 1 downto 0 do

    ...

    end

  3. bugake

    For the uninformed: counting backwards in a for loop is faster because comparing an unsigned integer against 0 is generally faster than comparing it against any other value.

    It also says not to use `for (i >= 0)` because any unsigned integer is >= 0, and the loop will never end.

  4. kccqzy

    This is why I prefer to use C++ and its reversed iterators. The rbegin and rend accessors are there in the containers from the beginning. It’s less error prone than the C version using indices. (Of course some situations require me to use indices, so I do use the i-->0 trick, but it is much rarer.)

  5. randomblock1

    I thought most people used the explicit version:

    for (size_t i = count; i > 0; --i) {

    // use array[i - 1]

    }

    You can also do something like:

    size_t index = i - 1;

    to not have to use i-1. I believe the compiler optimizes that out anyway to be identical.

More from this day

2026-10-30