I am subtracting to unsigned numbers and storing them to a signed type, and it just works. An I do not fully understand why this just works. Take the following example:
#include <stdio.h>
int main(void)
{
uint32_t a = 1;
uint32_t b = 2;
int32_t c = a - b;
printf("%"PRId32"\n", c);
return 0;
}
The result of this subtraction is -1, and it seems like it is only -1 because my computer is two's complement. Am I correct? I am looking at the C11 specification.
If we disect the following statement:
int32_t c = a - b;
We start with, according to operator precedence (as stated by annotation 85 on page 76), the subtraction:
a - b
C11 6.5.6/6:
The result of the binary - operator is the difference resulting from the subtraction of the second operand from the first.
This is -1 and thus will not fit. Conversion! C11 6.3.1.3/2:
Otherwise, if the new type is unsigned, the value is converted by repeatedly adding or subtracting one more than the maximum value that can be represented in the new type until the value is in the range of the new type.
So the actual value of a-b is 4294967295. Next up, the assignment operator: C11 6.5.16.1/2:
In simple assignment (=), the value of the right operand is converted to the type of the assignment expression and replaces the value stored in the object designated by the left operand.
So the unsigned value 4294967295 needs to be converted to a signed value. What are the rules?
C11 6.3.1.3/3:
Otherwise, the new type is signed and the value cannot be represented in it; either the result is implementation-defined or an implementation-defined signal is raised.
So this is fully implementation defined and thus ends up being -1, since that is how my implementation is.
Is this really the case? Would the code result in a different value if I run it on a system with one's complement system? Or am I overlooking something?