How does subtracting the character '0' fro

2019-01-12 00:28发布

问题:

This method works in C, C++ and Java. I would like to know the science behind it.

回答1:

The value of a char can be 0-255, where the different characters are mapped to one of these values. The numeric digits are also stored in order '0' through '9', but they're also not typically stored as the first ten char values. That is, the character '0' doesn't have an ASCII value of 0. The char value of 0 is almost always the \0 null character.

Without knowing anything else about ASCII, it's pretty straightforward how subtracting a '0' character from any other numeric character will result in the char value of the original character.

So, it's simple math:

'0' - '0' = 0  // Char value of character 0 minus char value of character 0
// In ASCII, that is equivalent to this:
48  -  48 = 0 // '0' has a value of 48 on ASCII chart

So, similarly, I can do integer math with any of the char numberics...

(('3' - '0') + ('5' - '0') - ('2' - '0')) + '0') = '6'

The difference between 3, 5, or 2 and 0 on the ASCII chart is exactly equal to the face value we typically think of when we see that numeric digit. Subtracting the char '0' from each, adding them together, and then adding a '0' back at the end will give us the char value that represent the char that would be the result of doing that simple math.

The code snippet above emulates 3 + 5 - 2, but in ASCII, it's actually doing this:

((51 - 48) + (53 - 48) - (50 - 48)) + 48) = 54

Because on the ASCII chart:

0 = 48
2 = 50
3 = 51
5 = 53
6 = 54


回答2:

In C the + and - operators apply integer promotion*1 to their arguments, thus the result of subtracting (or adding) two chars is an int*2.

From the C-Standard:

5.1.2.3 Program execution

[...]

10 EXAMPLE 2 In executing the fragment

char c1, c2;
/* ... */
c1 = c1 + c2;

the ‘‘integer promotions’’ require that the abstract machine promote the value of each variable to int size and then add the two ints [...]

Applying this to the OP's implicitly given use case of

char c = 42;
... = c - `0`;

This would be lead to the above being the same as:

... = (int) c - (int) `0`; /* The second cast is redundant, as per Jens' comment. */              
      ^                ^
      +------ int -----+

*1: If the operators arguments have a lower rank than int they are promoted to an int.
*2: char has a lower rank than int.



回答3:

There's no change going on. '0' is an int in C. It is a fancy way to write 48 (assuming ASCII).

You can convince yourself of this fact by computing the size of '0':

  printf ("sizeof '0'   is %zu\n", sizeof '0');
  printf ("sizeof(char) is %zu\n", sizeof(char));

which in the first line very likely prints 4 (or 2) but probably not 1 like in the second row (again: in C; it's different for C++).



回答4:

The numeric constant 0, without any qualifications, has type int. The result of the binary subtraction operation on a char and an int also has type int due to the usual type promotion process.



标签: java c++ c char int