Reputation: 563
I am having a hard time understanding the output of the following program.
int main(){
char y = 0x02;
y = y-0x03;
printf("0x%x %d",y,sizeof(y));
return 0;
}
The output that I am getting is
0xffffffff 1
I know so far is that if I add two hexadecimal values their binary values are added. The same is done for subtraction using the concept of borrow (please correct me if I am wrong)
Examples
111 - 001 = 110 (in binary) 110 - 001 = 101 (using carry from second LSB in first operand)
In the case of addition of two hexadecimal values if the values overflow char
they are basically mod 256. That is if I write a program as
int main(){
char y = 0x03;
y = y+0xff;
printf("0x%x",y);
return 0;
}
I will get output of
0x2
But in case of subtraction, if I run the first program, the expected output should be
0xff
So my question is since the above subtraction should be
00000010 - 00000011
in binary, where the borrow is coming from? and why I am getting this
0xffffffff
weird output?
Upvotes: 1
Views: 3414
Reputation: 112
This happens because of a tricky concept called integer promotions.
Basically, your single-byte char are being converted to 4-byte integers to handle your operations. So:
0x02 - 0x03
Becomes:
0x00000002 - 0x00000003
Which happens to be 0xffffffff (because that's how -1 is represented as an integer).
Upvotes: 0
Reputation: 753615
Two parts to the answer:
Arguments to printf()
— or the ...
portion of any variadic function — undergo default promotion. For type char
, that means the value is converted to int
.
You have signed char
on your machine, so the value is sign-extended. That is, the 0xFF stored in y
is converted to 0xFFFFFFFF
, which is what you see printed.
If you have a library that supports a sufficiently modern specification of printf()
, you could use:
printf("%hhx %zu\n", y, sizeof(y));
The hhx
says 'convert to char
and then print'. The z
length modifier %zu
is one of the correct formats for printing size_t
values such as those returned by sizeof()
. Failing that, use y & 0xFF
or (unsigned char)y
instead of a plain y
as the argument to printf()
.
Upvotes: 4
Reputation: 5920
I know so far is that if I add two hexadecimal values they are converted to binary and then are added. The same is done for subtraction using the concept of borrow (please correct me if I am wrong)
You are wrong. Hexadecimal, decimal, octal, etc is a form to represent a number. Down below it is always a sequence of bits.
You are getting "weird" output because of %x
format specification. Your 1 byte char value is converted to the unsigned int.
Upvotes: 1
Reputation: 48572
Most computer systems today use two's complement to represent negative numbers. In this system, negative numbers are represented as the bitwise inverse of one less than their absolute value. Negative one represented in this way is the bitwise inverse of 1 - 1 = 0, which has all of its bits on.
Also, note that signed overflow is undefined behavior in C, so unless you use a compiler option like gcc's -fwrapv
, so your example with mod 256 above isn't guaranteed to work.
Upvotes: 0