← Exercises|

What happens at the edge of a type

Predict4 of 14 · about 7 min

What happens at the edge of a type

Add 1 to the largest unsigned int and it wraps around to 0. The standard says so: unsigned arithmetic is arithmetic modulo 2 to the power of the number of bits. You can rely on it.

Add 1 to the largest **signed** int and the standard says nothing at all. That is "undefined behaviour": the compiler is allowed to assume it never happens, and modern optimisers do exactly that — they will delete an overflow check you wrote, because the only way it could be true is if overflow had already happened.

This runtime stops and tells you when signed overflow happens. A real compiler usually lets it pass quietly and produces a wrong number, or deletes your check. That is the difference this exercise is about.

Example

#include <stdio.h>
#include <limits.h>

int main(void) {
    unsigned int u = UINT_MAX;
    printf("%u -> %u\n", u, u + 1u);
    return 0;
}

prints: "4294967295 -> 0\n"

Before you run it

unsigned char c = 250;
c = c + 10;
printf("%d\n", c);

What is printed?

Your task

Fill in unsigned int wrap_add(unsigned int a, unsigned int b) so that it returns a + b. main calls it twice: once at the top of the range, where the answer wraps to 0, and once in the middle, where it does not. The point is that you need no special trick — unsigned addition already wraps.

Stuck?

Explain it

Why is if (x + 1 < x) a broken way to check a signed int for overflow?

Not graded — this is for you.

Where this goes

Project 2 asks you to demonstrate both behaviours and explain the difference. This is the demonstration in miniature.