The following code will produce a segfault due to integer overflow when i reaches -1. If I change "unsigned int i" to "char i", then it will work fine but will generate a compiler warning "array subscript has type 'char'". Declaring it as "int i" will work fine and there won't be compiler warning but it feels like there should be. After all int is signed as well and could go also negative. My question is, is there a safe, elegant, idiomatic way to write such loops in C?
#include <stdio.h>
int main() {
unsigned int i;
char a[10] = {0};
for (i = 9; i >= 0; i--) {
printf("a[%d]: %d\n", i, a[i]);
}
return 0;
}
The loop in your code indeed does not work as the test
i >= 0is always true. Compiling with extra warnings will spot this problem.To avoid this problem,
ishould be initialized to10, the test should bei > 0andishould be decremented at the start of each iteration instead of after it:Combining the test and the decrement produces the classic down loop that works for both signed and unsigned index types:
The test
i-- > 0is only false fori == 0, butiis decremented as a side effect, so the first iteration uses the value9inside the loop body, the second uses8... and the last uses0, the value ofiafter the last decrement. The next next will evaluate to false and leaveiwith the valueUINT_MAX.Another advantage of this technique is
iis initialized to the number of elements,10, which is also the number of iterations, not9as in the question code.Note also that
i-- > 0can be writteni --> 0as explained in this popular question. Whilei-- > 0is idiomatic in C,i --> 0is not. Whether one is more elegant than the other is a matter of opinion