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 value 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 a 16 is 10 10 , 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.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.