C中十六进制转十进制数时48和87的值指的是什么?

What do 48 and 87 values refer to when converting hexadecimal to decimal number in C?

我想了解将十六进制数转换为十进制数的过程,尤其是在将每个十六进制数字转换为其十进制值时。

假设hexVal的数字i等于'0'到'9'之间的任何字符时,其decVal等于hexVal减去48然后由digitBase计时:

if ((hexVal[i] >= '0') && (hexVal[i] <= '9')) {
    decVal += (hexVal[i] - 48) * digitBase;
    ...
}

我知道 48 是“0”的 ASCII 值。 我怀疑的是当 hexVal 的数字 i 等于范围 'A' 到 'F' 和 'a' 到 'f' 时值 55 和 87 来自哪里:

else if ((hexVal[i] >= 'A') && (hexVal[i] <= 'F')) {
    hexToDec += (hexVal[i] - 55) * digitBase;
    ...
}

else if ((hexVal[i] >= 'a') && (hexVal[i] <= 'f')) {
    hexToDec += (hexVal[i] - 87) * digitBase;
    ...
}

上面的代码块是从以下函数中提取的,该函数可以很好地将十六进制数转换为其等效的十进制数。

int conv_hex_to_dec(char hexVal[]) {

    int hexToDec = 0;
    int len = strlen(hexVal);
    int digitBase = 1; 

    // Extract hex characters as digits from last character
    for (int i = len - 1; i >= 0; i--) {

        if ((hexVal[i] >= '0') && (hexVal[i] <= '9')) {
            hexToDec += (hexVal[i] - 48) * digitBase;
            digitBase = digitBase * 16;
        }

        else if ((hexVal[i] >= 'A') && (hexVal[i] <= 'F')) {
            hexToDec += (hexVal[i] - 55) * digitBase; 
            digitBase = digitBase * 16;
        }
        else if ((hexVal[i] >= 'a') && (hexVal[i] <= 'f')) {
            hexToDec += (hexVal[i] - 87) * digitBase; 
            digitBase = digitBase * 16;
        }
        else {
            printf("Invalid hex val");
        }
    }

    return hexToDec;
}

任何解释将不胜感激。

谢谢。

48是'0'的ASCII码; 'A' 和 'a' 的 ASCII 码分别是 65 (55 = 65-10) 和 97 (87 = 97 - 10)。

这是为什么 "magic numbers" 代码不好的一个主要例子。

此代码假定字符编码为 ASCII。相关数字是:

  • 48:'0'
  • 的 ASCII 码
  • 65:'A'
  • 的 ASCII 码
  • 97:'a'
  • 的 ASCII 码

所以在这行代码中:

decVal += (hexVal[i] - 48) * digitBase;

就是'0'的ASCII码减去hexVal[i]的ASCII码。这会将 '0''9' 范围内的字符转换为 0 到 9 范围内的值。

同样,这个:

hexToDec += (hexVal[i] - 55) * digitBase;

'A'的ASCII码减去hexVal[i]的ASCII码,再加10,即把'A''F'范围内的一个字符转换成一个值在 10 到 15 的范围内。类似地,检查 87,这会将 'a''f' 范围内的字符转换为 10 到 15 范围内的值。

更好的写法是:

    if ((hexVal[i] >= '0') && (hexVal[i] <= '9')) {
        hexToDec += (hexVal[i] - '0') * digitBase;
        digitBase = digitBase * 16;
    }

    else if ((hexVal[i] >= 'A') && (hexVal[i] <= 'F')) {
        hexToDec += (hexVal[i] - 'A' + 10) * digitBase; 
        digitBase = digitBase * 16;
    }
    else if ((hexVal[i] >= 'a') && (hexVal[i] <= 'f')) {
        hexToDec += (hexVal[i] - 'a' + 10) * digitBase; 
        digitBase = digitBase * 16;
    }

因为reader更清楚意图是什么。