One point to avoid tripping on:
#include <stdio.h>
#include <limits.h>
int main() {
int x = INT_MIN;
int y = -x;
printf("%d, %d\n", x, y);
printf("%d\n", x+y);
}
prints on my machine
-2147483648, -2147483648
0
In twos complement, there is one more negative number than there are positives. So you might worry that nothing happens when you try to negate INT_MIN. But, it all works out correctly! For the $k$-bit signed integers to be isomorphic to $\mathbb{Z} / 2^k$ you must line them up correctly, e.g. for $k=3$:
0 1 2 3 4 5 6 7
0 1 2 3 -4 -3 -2 -1
For example the element "6" of $\mathbb{Z} / 2^k$ is represented by -2 and "4" by -4. In particular it's true that -(-4) = -4, because in this group, 4 is its own additive inverse. So the program above is correct (note: correct according to $\mathbb{Z}/2^k$, not $\mathbb{Z}$), because $-x = x$ and $x + x = 0$ mod $2^k$.
In general INT_MIN corresponds to $2^{k-1}$ and is its own additive inverse:
0 1 ... 2^(k-1)-1 2^(k-1) ... 2^k - 1
0 1 ... INT_MAX INT_MIN ... -1
uint64_t
is only a ring: not all elements have a multiplicative inverse. $\endgroup$