1

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?

Ajay Pal
  • 543
  • 4
  • 13
  • 1
    `sizeof` returns a `size_t` which [must be printed out using `%zu`](http://stackoverflow.com/q/940087/995714) – phuclv Mar 09 '17 at 04:14

4 Answers4

4

Two parts to the answer:

  1. Arguments to printf() — or the ... portion of any variadic function — undergo default promotion. For type char, that means the value is converted to int.

  2. 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().

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
1

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.

Ari0nhh
  • 5,720
  • 3
  • 28
  • 33
  • Yes, I should have rephrased that, I did not meant "converted" to binary. But the addition and subtraction are in the binary right. ? – Ajay Pal Mar 09 '17 at 04:27
0

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.

0

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).