Step 2 of 8
Unsigned wraparound
Unsigned integers can't be negative. Instead, their arithmetic is defined to wrap around: results are taken modulo 2 to the power N, like a car's odometer rolling over. Go below 0 and you land at the maximum; go above the maximum and you land at 0.
#include <stdio.h>
#include <stddef.h>
int main(void) {
unsigned int x = 0;
x = x - 1;
printf("%u\n", x);
unsigned char c = 250;
c = c + 10;
printf("%u\n", c);
size_t n = 3;
for (size_t i = n; i-- > 0; ) {
printf("%zu ", i);
}
printf("\n");
return 0;
}
4294967295
4
2 1 0
This wrapping is well-defined (unlike signed overflow, next step), and useful for hashing, checksums and bit manipulation.
The countdown trap
size_t (the type of sizeof, strlen and array sizes) is unsigned. That makes this innocent-looking loop run forever:
for (size_t i = n - 1; i >= 0; i--) /* i >= 0 is ALWAYS true */
When i is 0 and gets decremented, it wraps to the maximum value instead of becoming -1, so the condition never fails. (If n is 0, n - 1 is already the maximum.) GCC warns about this with -Wextra (comparison of unsigned expression in '>= 0' is always true), but the compiler on this site doesn't, so you have to recognize the pattern yourself.
The idiomatic fix, used in the example, tests before decrementing: for (size_t i = n; i-- > 0; ). The condition uses the old value of i (is it above 0?) and then decrements, so the body sees n-1 down to 0, and it's correct even when n is 0.
Your turn: read a count n and then n integers into an array (at most 100), and print them in reverse order on one line, separated by spaces. Use a size_t index for the reverse loop.
Previous: Sizes and limits Next: Signed overflow is undefined