Reverse iteration with an unsigned loop variable

2020-05-11 07:27发布

I've been discussing the use of size_t with colleagues. One issue that has come up is loops that decrement the loop variable until it reaches zero.

Consider the following code:

for (size_t i = n-1; i >= 0; --i) { ... }

This causes an infinite loop due to unsigned integer wrap-around. What do you do in this case? It seems far to easy to write the above code and not realise that you've made a mistake.

Two suggestions from our team are to use one of the following styles:

for (size_t i = n-1; i != -1 ; --i) { ... }

for (size_t i = n; i-- > 0 ; ) { ... }

But I do wonder what other options there are...

标签: c++ c
10条回答
混吃等死
2楼-- · 2020-05-11 07:47

Another solution (available on POSIX compliant systems) that I found to be simple and effective is to replace size_t with ssize_t:

for (ssize_t i = n-1; i >= 0; --i) { ... }

On non-POSIX systems, ssize_t is not difficult to typedef: Alternative to ssize_t on POSIX-unconformant systems

查看更多
可以哭但决不认输i
3楼-- · 2020-05-11 07:49

Unsigned integers are guaranteed to wrap around nicely. They just implement arithmetic modulo 2N. So an easy to read idiom is this one:

for (size_t i = n-1; i < n ; --i) { ... }

this sets the variable to the initial value that you want, shows the sense of the iteration (downward) and gives precisely the condition on the values that you want to handle.

查看更多
三岁会撩人
4楼-- · 2020-05-11 07:52

i != -1 relies on the -1 being silently cast to a size_t, which seems fragile to me, so, of the alternatives you present, I'd definitely go with the post-decrement one. Another possibility (esp. if you don't actually need i in the loop body but just need to iterate on an array in reverse order) would be to wrap the array in a std::-like container and use an iterator on the wrapper, with the rbegin and rend methods. E.g., Boost.Array would support the latter choice.

查看更多
▲ chillily
5楼-- · 2020-05-11 07:56
size_t i = n-1;

do  { 
  ...
} while ( i-- != 0);

You may wrap that with a if (n > 0) if necessary.

查看更多
登录 后发表回答