0

I observed that, when a unsigned char variable stores the value 0 (000000002) and it gets decremented by 1 (000000012), the variable value turns into 255 (111111112), which is the highest value that a unsigned char variable can hold.

My question is: why 000000002 - 000000012 turns into 111111112? (I want to see the arithmetic behind it)

The C code in which i observed it was this one:

#include <stdio.h>

main(){

  unsigned char c = 0;

  unsigned char d = c - 1;

  printf("%d\n%d", c, d);

}

When it runs, the following output is shown:

0
255
samuel
  • 3
  • 3
  • 1
    It's called modular arithmetic, and it's a quite reasonable approach to dealing with unsigned numbers. And the same reason why the answer to "subtract 1 hour from 00:00" will give you "23:00", instead of "-01:00". – vgru Feb 05 '20 at 14:27
  • 3
    You know how when a six-digit car odometer continues from 999999, it goes to 000000? If it were going backward from 000000, it would go to 999999. Going from 00000000 to 11111111 in binary is the same thing. – Eric Postpischil Feb 05 '20 at 14:28
  • In detail, process the digits from right to left: First we have 0 minus 1: 1 is bigger, so we “borrow” 1 from the digit to the left. Then we have 10 minus 1, which results in 1. In the next position, we have 0 minus 0 minus a borrow of 1, so it is 0 minus 1. Again, we borrow and get 1 as a result. This continues up to the last position, where we again borrow 1 and get 1 as a result. Now we have eight 1s as result bits and a borrow from the position to the left, which is outside the eight bits and is discarded or ignored. – Eric Postpischil Feb 05 '20 at 14:30
  • 2
    what did you expect? – 0___________ Feb 05 '20 at 14:32
  • @EricPostpischil, but how can we borrow 1 from 0? – samuel Feb 05 '20 at 14:39
  • @samuel you need to accept it as the axiom. . – 0___________ Feb 05 '20 at 14:42
  • 1
    @samuel: Well, 0 does not have enough to borrow, so you borrow 1 from its left. That makes it 10, and you can subtract 1 from that. As I write, that works all the way up to the last digit, at which point we have borrowed 100000000 (256 in decimal). I.e., instead of 0000 0000 − 0000 0001, we have 1 0000 0000 - 0000 0001, which is clearly 1111 1111. It only works if you are allowed to borrow a 1 0000 0000 that you do not have. Which is the same as working modulo 256. – Eric Postpischil Feb 05 '20 at 14:45

1 Answers1

1

See here:

Unsigned integer arithmetic is always performed modulo 2n where n is the number of bits in that particular integer. E.g. for unsigned int, adding one to UINT_MAX gives ​0​, and subtracting one from ​0​ gives UINT_MAX.

So in your example, since unsigned char is usually 8 bit, you get 28-1 = 255.

Community
  • 1
  • 1
Blaze
  • 16,736
  • 2
  • 25
  • 44