I Learned About 2's Complement
and unsigned and signed int. So I Decided to test my knowledge , as far as i know that a negative number is stored in 2's complement
way so that addition and subtraction would not have different algorithm and circuitry would be simple.
Now If I Write
int main()
{
int a = -1 ;
unsigned int b = - 1 ;
printf("%d %u \n %d %u" , a ,a , b, b);
}
Output Comes To Be -1 4294967295 -1 4294967295
. Now , i looked at the bit pattern and various things and then i realized that -1
in 2's complement is 11111111 11111111 11111111 11111111
, so when i interpret it using %d , it gives -1
, but when i interpret using %u
, it treat it as a positive number and so it gives 4294967295
. I Checked the Assembly Of the code is
.LC0:
.string "%d %u \n %d %u"
main:
push rbp
mov rbp, rsp
sub rsp, 16
mov DWORD PTR [rbp-4], -1
mov DWORD PTR [rbp-8], -1
mov esi, DWORD PTR [rbp-8]
mov ecx, DWORD PTR [rbp-8]
mov edx, DWORD PTR [rbp-4]
mov eax, DWORD PTR [rbp-4]
mov r8d, esi
mov esi, eax
mov edi, OFFSET FLAT:.LC0
mov eax, 0
call printf
mov eax, 0
leave
ret
Now here -1
is moved to the register both the times in unsigned and signed . What i want to know if reinterpretation is only that matters , then why do we have two types unsigned
and signed
, it is printf
format string %d
and %u
that matters ?
Further what really happens when i assign negative number to a unsigned integer (I learned That The initializer converts this value from int
to unsigned int
. ) but in the assembly code I did not saw such a thing. So what really happens ??
And How does Machine knows when it has to do 2's complement
and when not , does it see the negative sign and performs 2's complement
?
I have read almost every question and answer you could think this question be duplicate of , but I could not find a satisfactory solution.
Choice of signed integer representation is left to the platform. The representation applies to both negative and non-negative values - for example, if
11012
(-5) is the two's complement of01012
(5), then01012
(5) is also the two's complement of11012
(-5).The platform may or may not provide separate instructions for operations on signed and unsigned integers. For example, x86 provides different multiplication and division instructions for signed (
idiv
andimul
) and unsigned (div
andmul
) integers, but uses the same addition (add
) and subtraction (sub
) instructions for both.Similarly, x86 provides a single comparison (
cmp
) instruction for both signed and unsigned integers.Arithmetic and comparison operations will set one or more status register flags (carry, overflow, zero, etc.). These can be used differently when dealing with words that are supposed to represent signed vs. unsigned values.
As far as
printf
is concerned, you're absolutely correct that the conversion specifier determines whether the bit pattern0xFFFF
is displayed as-1
or4294967295
, although remember that if the type of the argument does not match up with what the conversion specifier expects, then the behavior is undefined. Using%u
to display a negativesigned int
may or may not give you the expected equivalent unsigned value.