此代码为什么要将十六进制转换为十进制

问题描述:

此代码将一个十六进制数字转换为十进制值。此代码为什么要将十六进制转换为十进制

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); 

我不完全理解它是如何工作的。我可以看到不同的东西从char变量中减去,这取决于它是数字还是字母。我可以理解数字转换的部分,但我不明白当字符是字母时为什么必须添加10。

减去tolower(ch) - 'a'会将字符映射到字母a..f的范围0..5的数​​字。然而,十六进制数字a(十进制)的值是10 ,因此要将范围移回到10..15所需的位置,需要添加10。

也许这有助于:

+---------+------------+-----------------+-------------+ 
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  | 
+---------+------------+-----------------+-------------+ 

通知如何“所得的值”列复位回到0在a,这是不需要它根据最后的“位值”栏是,它以十进制显示每个十六进制数字的值。

表达式ch - '0'的工作原理是因为在C中“0 ...之后的每个字符的值应比先前的值大1”(C99第5.2.1节)。

因此,例如,字符'3'的值大于'0'值3更大,所以当你减去这两个值,你靠运气得到整数3

表达tolower(ch) - 'a' + 10作品,因为除了上述数​​字约束外,所有字符值都是实现定义的。

所以,当你减去'c' - 'a'你得到2(并且,加10,你得到12--该数字的正确值),因为大多数计算机工作在ASCII或EBCDIC。但是当你在DS9K上运行这个程序时,你可能会得到-42。

为了确保便携性,您需要依次将ch与六个字母中的每一个进行比较。这就是为什么有些系统提供了digittoint()功能。