Iterating Backwards in C

Hacker News Top News

Summary

The author explains the common mistakes when iterating backwards in C and presents the clean idiom `for(size_t i = count; i--; )`, which avoids signed-index and wrap-around pitfalls, especially as LLM-generated code repeats the buggy versions.

No content available
Original Article
View Cached Full Text

Cached at: 10/30/26, 03:07 AM

# Iterating Backwards in C Source: [https://www.davidpriver.com/Iterating-backwards-in-C.html](https://www.davidpriver.com/Iterating-backwards-in-C.html) This is shorter than some of my other posts, but I keep seeing people doing this wrong\. It's even worse now in the LLM era\. Let's say you have a buffer and a counter and you need to iterate it backwards for some reason: ``` _Bool find_last(size_t count, int *haystack, int needle, size_t *where); ``` Almost everyone can do the forward version on autopilot: ``` for(size_t i = 0; i < count; i++){ if(haystack[i] == needle){ *where = i; return 1; } } return 0; ``` So they try to do the same thing, just iterating backwards: ``` for(size_t i = count - 1; i >= 0; i--){ } ``` But that doesn't work at all\!i \>=0is tautologically true \(modern compilers will warn\)\. Even worse, if count is 0,iimmediately becomesSIZE\_MAX\. Ok, so they try the next version: ``` for(ssize_t i = count - 1; i >= 0; i--){ } ``` This works in practice with a signed index but introduces some problems: - Now your index variable is signed, which can cause problems when used in expressions due to C's conversion rules\. - ssize\_tis a POSIX thing so you'd have to define it yourself on windows\. - If your type is 32 bit, you run into promotion problems and might even run into truncation problems\. - This spelling of the loop is overcomplicated and requires special inspection each time\. Did you get the second\-clause condition right? Avoiding these problems brings us to the actual, proper way to iterate backwards in C: ``` for(size_t i = count; i--; ){ } ``` So much simpler\! Let's break it down: The key is the postdecrement operator oni\. It decrementsibut yields the value thatiwas before the operation\. In this case, this means that in the body of the loopiis always in bounds as its value will be decremented after initialization so it is at mostcount \- 1, while the condition checks that if it was previously 0 then the loop ends\.iwill wrap around, but unsigned wrap\-around is well defined in C so that is not a problem\. The final version: ``` _Bool find_last(size_t count, int *haystack, int needle, size_t *where){ for(size_t i = count; i--; ){ if(haystack[i] == needle){ *where = i; return 1; } } return 0; } ``` Doing it this way means you don't have to mess around with converting to a signed loop index and look at how simple that loop is\! You can tell at a glance if someone has implemented the reverse loop properly or not\. So please\! If you see someone trying to iterate backwards, show them this way to do it\!

Similar Articles

Going Backward

Lobsters Hottest

This article explores the design evolution of Go's slices.Backward function, illustrating different implementations from simple reversal to callback-based iterators, and explains why the standard library's iterator signature looks the way it does.

Getting silly with C, part &((int*)-8)[3]

Lobsters Hottest

A humorous educational article covering C programming fundamentals such as forward declarations, operator precedence, unconditional jumps, and basic arithmetic with intentionally silly code examples.

The C ``Clockwise/Spiral Rule''

Hacker News Top

A classic technique for parsing complex C declarations by following a clockwise/spiral rule, with worked examples.

Neoclassical C++: segmented iterators revisited

Hacker News Top

Revisits Matt Austern's 2000 paper on segmented iterators, which enable hierarchical algorithms to exploit data structure segmentation for performance, and discusses modern adoption in libc++ and Boost libraries.