Why does this code work to convert hexadecimal to decimal
This code will convert one hexadecimal digit into a decimal value.
int value;
// ch is a char variable holding a hexadecimal digit
if (isxdigit(ch))
if (isdigit(ch))
value = ch - '0';
else
value = tolower(ch) - 'a' + 10;
else
fprintf(stderr, "%c is not a valid hex digit", ch);
I don't fully understand how it works though. I can see that different things are subtracted from the char variable depending on whether it is a number or a letter. I can understand the part where a number gets converted, but I don't understand why 10 has to be added to the val开发者_开发技巧ue when the character is a letter.
The subtraction of tolower(ch) - 'a'
will map the character to a number in the range 0..5 for the letters a..f. However, the (decimal) value of the hexadecimal digit a16 is 1010, so to move the range back up to 10..15 where it needs to be, 10 is added.
Perhaps this helps:
+---------+------------+-----------------+-------------+
Character | Subtracted | Resulting value | Digit value |
+---------+------------+-----------------+-------------+
| '0' | '0' | 0 | 0 |
| '1' | '0' | 1 | 1 |
| '2' | '0' | 2 | 2 |
| '3' | '0' | 3 | 3 |
| '4' | '0' | 4 | 4 |
| '5' | '0' | 5 | 5 |
| '6' | '0' | 6 | 6 |
| '7' | '0' | 7 | 7 |
| '8' | '0' | 8 | 8 |
| '9' | '0' | 9 | 9 |
| 'a' | 'a' | 0 | 10 |
| 'b' | 'a' | 1 | 11 |
| 'c' | 'a' | 2 | 12 |
| 'd' | 'a' | 3 | 13 |
| 'e' | 'a' | 4 | 14 |
| 'f' | 'a' | 5 | 15 |
+---------+------------+-----------------+-------------+
Notice how the "resulting value" column resets back to 0 at 'a', which is not where it needs to be according to the final "digit value" column, which shows each hexadecimal digit's value in decimal.
The expression ch - '0'
works because in C "the value of each character after 0 ... shall be one greater than the value of the previous" (C99 section 5.2.1).
So, for example, the value of the character '3'
is 3 greater than the value of '0'
, so when you subtract these two values, you get the integer 3.
The expression tolower(ch) - 'a' + 10
works by luck, because, except for the above constraint for digits, all values of characters are implementation-defined.
So when you subtract 'c' - 'a'
you get 2 (and, adding 10, you get 12 – the correct value of that digit), because most computers work in ASCII or EBCDIC. But when you run this program on the DS9K, you might get −42.
To be truly portable you would need to compare ch
to each of the six letters in turn. That's why some systems provide a digittoint()
function.
精彩评论