C: unary minus operator behavior with unsigned operands

Yes, 6.2.5c9 is exactly the paragraph that you looked for.


The behavior of the unary minus operator on unsigned operands has nothing to do with whether a machine uses two's-complement arithmetic with signed numbers. Instead, given unsigned int x,y; the statement y=-x; will cause y to receive whatever value it would have to hold to make x+y equal zero. If x is zero, y will likewise be zero. For any other value of x, it will be UINT_MAX-x+1, in which case the arithmetic value of x+y will be UINT_MAX+1+(y-y) which, when assigned to a unsigned integer, will have UINT_MAX+1 subtracted from it, yielding zero.


In every implementation I know of, a negative is calculated as two's complement...

int a = 12;
int b = -a;
int c = ~a + 1;
assert(b == c);

...so there is really no physical difference between negative signed and "negative" unsigned integers - the only difference is in how they are interpreted.

So in this example...

unsigned a = 12;
unsigned b = -a;
int c = -a;

...the b and c are going to contain the exact same bits. The only difference is that b is interpreted as 2^32-12 (or 2^64-12), while c is interpreted as "normal" -12.

So, a negative is calculated in the exact same way regardless of "sign-ness", and the casting between unsigned and signed is actually a no-op (and can never cause an overflow in a sense that some bits need to be "cut-off").