for (size_t i = 0; i < length; i++) ...
The following causes an unsigned integer underflow and is an infinite loop: for (size_t i = length - 1; i >= 0; i--) ... for (size_t i = 0; i < length; i++) ...
The following causes an unsigned integer underflow and is an infinite loop: for (size_t i = length - 1; i >= 0; i--) ... for (size_t i = length - 1; i < length; i--) ...
You are also free to start at any other (not necessarily in-bounds) index, just like with ascending iteration.[1] https://gustedt.wordpress.com/2013/07/15/a-praise-of-size_t-...
Seriously though, while the idiom does work for unsigned integers, it's a bad idiom to learn [makes code reviews harder]. The post-decrement one in the loop body works with everything (signed/unsigned), and it's well known.
why doesn't that loop end instantly?
I mean length - 1 < length should always be true, right?
Or does it only terminate when the number underflows? Terribly confused here
for(initialize; condition; increment) { ... }
to: initialize;
while(condition) {
...
increment
}
(more or less, some scoping things not encompassed by the above; this is also how pretty much every for loop in a C-syntax language works) The condition of a for loop is equivalent to a while loop's condition. So yes, length - 1 < length will be true on the first iteration, which is fine because the loop continues as long as that condition is true.What the above approach takes advantage of is that when underflow eventually happens you'll have this condition:
MAXINT < length
Which will terminate it for all possible values of length.Also, that behavior is not guaranteed. The programmer would need to be aware of how the particular machine in question actually handles that.
Then again, that's C.
for (size_t i = n; i-- > 0 ;) ...
Or count from `length` to 1, but subtract 1 in the loop body, or count up and subtract the length in the loop body. Any modern compiler should be able to optimise these to be equivalent.In the majority of cases, counting down is not necessarily. Nor is ordered iteration. Most languages have a `for each` style syntax that's preferable anyway.
size_t i = length;
while (i--) ... for (size_t i = length; i-- > 0 ; ) ...
that several other people posted would not execute for index 0. Shouldn't it be this instead? for (size_t i = length; --i > 0 ; ) ... for (size_t i = length; i-- > 0; )...
It's surprising how often the issue pops, it works well with both signed and unsigned integers.(edit) I've started with one based indexing (basic)... mixed with 0 based (assembly), more 1 based (pascal), then more stuff (all zero based). I am, yet, to see a real advantage of a one based indexing... after the initial process.
If performance matters, you should experiment with __builtin_prefetch, which is available in clang and GCC.
for (size_t i = length; i > 0; i--) {
// ...
item = array[i - 1];
(This is how reverse iterators work in C++.) for (size_t i = 0; i < length; i++) {
size_t j = (length - 1) - i;
...
}
EDIT: change i to j const j = (length - 1) - i;
in that case. Much safer.Makes my brain hurt, but I think this will only run through the loop one time looking at the last element of the array.