The C language still surprises me

What does this code print?

1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>
 
int main()
{
    signed char x = -128;
 
    if (x < 0) {
        x = -x;
    }
    printf("x = %d\n", (int) x);
    return 0;
}

I’ve been reading Matters Computational, an excellent (free) book by Jörg Arndt about programming and algorithms. It surprised me in the very first pages with this pitfall in two’s complement – there is always a number that is equal to its own negative, besides zero. The code above prints −128!

In hindsight, it’s pretty obvious. A signed char can hold values from −128 to 127 — that is, there are 127 positive numbers and 128 negative numbers! Therefore, it’s impossible to the unary negative operator to be one-to-one. The smallest negative number will always be mapped to itself. Of course, this also applies to int, etc.

The main implication of this fact is that, after the innocent-looking code

if (x < 0) x = -x;

x is not guaranteed to be positive!