C/C++ Arena

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