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 char
s 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 twoint
s [...]
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.