Reputation: 1513
Is the following code, safe to iterate an array backward?
for (size_t s = array_size - 1; s != -1; s--)
array[s] = <do something>;
Note that I'm comparing s
, which is unsigned
, against -1
;
Is there a better way?
Upvotes: 1
Views: 157
Reputation: 67546
IMO in the iterations use large enough signed value. It ss easier to read by humans.
Upvotes: 0
Reputation: 85767
This code is surprisingly tricky. If my reading of the C standard is correct, then your code is safe if size_t
is at least as big as int
. This is normally the case because size_t
is usually implemented as something like unsigned long int
.
In this case -1
is converted to size_t
(the type of s
). -1
can't be represented by an unsigned type, so we apply modulo arithmetic to bring it in range. This gives us SIZE_MAX
(the largest possible value of type size_t
). Similarly, decrementing s
when it is 0
is done modulo SIZE_MAX+1
, which also results in SIZE_MAX
. Therefore your loop ends exactly where you want it to end, after processing the s = 0
case.
On the other hand, if size_t
were something like unsigned short
(and int
bigger than short
), then int
could represent all possible size_t
values and s
would be converted to int
. In other words, the comparison would be done as (int)SIZE_MAX != -1
, which would always return false
, thus breaking your code. But I've never seen a system where this could happen.
You can avoid any potential problems by using SIZE_MAX
(which is provided by <stdint.h>
) instead of -1
:
for (size_t s = array_size - 1; s != SIZE_MAX; s--)
...
But my favorite solution is this:
for (size_t s = array_size; s--; )
...
Upvotes: 3
Reputation: 2708
Well, s
will never be -1
, so your ending condition will never happen. s
will go from 0 to SIZE_MAX
, at which point your program will probably segfault from a memory access error. The better solution would be to start at the max size, and subtract one from everywhere you use it:
for (size_t s = array_size; s > 0; s--)
array[s-1] = <do something>;
Or you can combine this functionality into the for loop's syntax:
for (size_t s = array_size; s--;)
array[s] = <do something>;
Which will subtract one before going into the loop, but checks for s == 0
before subtracting 1.
Upvotes: 0