“十六进制”和“ASCII”并不是两种可以直接相互转换的数据类型。

(图片来源网络,侵删)
- 十六进制:是一种数字的表示方法,它用16个符号(0-9, A-F)来表示数值,数字
255用十进制表示,用十六进制表示就是0xFF,它们都指向同一个数值。 - ASCII:是一个字符编码标准,它规定了数字(0-255)与字符(如 'A', 'B', '1', '@')之间的对应关系。
我们通常所说的“十六进制转ASCII”,其实指的是以下两种常见的操作:
- 将一个十六进制字符串(如 "48656C6C6F")转换成一个ASCII字符串(如 "Hello")。 这是最常见的需求。
- 将一个十六进制数值(如
0x48)转换成它对应的ASCII字符(如 'H')。
下面我们分别对这两种操作进行详细的代码实现和解释。
十六进制字符串转ASCII字符串
这是最常见的场景,网络数据包、传感器数据、文件内容等常常以十六进制字符串的形式出现,我们需要将其转换成人类可读的文本。
核心思路
- 遍历输入的十六进制字符串,每两个字符(一个字节)组成一个十六进制数值。
- 将这个十六进制数值转换成对应的
char类型(ASCII码)。 - 将转换后的
char追加到结果字符串的末尾。 - 最后在结果字符串的末尾添加字符串结束符
\0。
示例代码
这个函数会处理小写和大写的十六进制字符。

(图片来源网络,侵删)
#include <stdio.h>
#include <string.h>
#include <ctype.h> // 用于 tolower 函数
/**
* @brief 将十六进制字符串转换为ASCII字符串
*
* @param hex_str 输入的十六进制字符串 ( "48656C6C6F")
* @param ascii_str 输出的ASCII字符串缓冲区 ( "Hello")
* @param ascii_buf_size 输出缓冲区的大小,防止溢出
* @return int 成功转换的字符数,如果失败则返回 -1
*/
int hexstr_to_asciistr(const char* hex_str, char* ascii_str, size_t ascii_buf_size) {
// 检查输入有效性
if (hex_str == NULL || ascii_str == NULL || ascii_buf_size == 0) {
return -1;
}
size_t hex_len = strlen(hex_str);
size_t ascii_len = hex_len / 2;
// 检查十六进制字符串长度是否为偶数,并且缓冲区是否足够大
if (hex_len % 2 != 0 || ascii_len >= ascii_buf_size) {
return -1;
}
for (size_t i = 0; i < hex_len; i += 2) {
// 将两个十六进制字符转换为一个字节
char high_nibble = tolower(hex_str[i]);
char low_nibble = tolower(hex_str[i + 1]);
// 检查字符是否为有效的十六进制字符
if (!((high_nibble >= '0' && high_nibble <= '9') || (high_nibble >= 'a' && high_nibble <= 'f')) ||
!((low_nibble >= '0' && low_nibble <= '9') || (low_nibble >= 'a' && low_nibble <= 'f'))) {
return -1; // 遇到非法字符
}
// 将十六进制字符转换为数值
// 'a' - 'a' + 10 = 10
// '5' - '0' = 5
int high_val = (high_nibble >= 'a') ? (high_nibble - 'a' + 10) : (high_nibble - '0');
int low_val = (low_nibble >= 'a') ? (low_nibble - 'a' + 10) : (low_nibble - '0');
// 组合成一个字节
unsigned char byte = (high_val << 4) | low_val;
// 将字节存入结果字符串
ascii_str[i / 2] = byte;
}
// 添加字符串结束符
ascii_str[ascii_len] = '\0';
return (int)ascii_len;
}
int main() {
const char* hex_input = "48656C6C6F20576F726C64"; // "Hello World"
char ascii_output[50]; // 确保缓冲区足够大
int result = hexstr_to_asciistr(hex_input, ascii_output, sizeof(ascii_output));
if (result != -1) {
printf("原始十六进制字符串: %s\n", hex_input);
printf("转换后的ASCII字符串: %s\n", ascii_output);
} else {
printf("转换失败!请检查输入字符串或缓冲区大小,\n");
}
// 测试带空格的十六进制字符串(需要先处理)
const char* hex_input_with_spaces = "48 65 6C 6C 6F";
char temp_hex[20];
char ascii_output_with_spaces[20];
// 先移除空格
int j = 0;
for (int i = 0; hex_input_with_spaces[i] != '\0'; i++) {
if (hex_input_with_spaces[i] != ' ') {
temp_hex[j++] = hex_input_with_spaces[i];
}
}
temp_hex[j] = '\0';
result = hexstr_to_asciistr(temp_hex, ascii_output_with_spaces, sizeof(ascii_output_with_spaces));
if (result != -1) {
printf("\n带空格的十六进制字符串: %s\n", hex_input_with_spaces);
printf("移除空格后: %s\n", temp_hex);
printf("转换后的ASCII字符串: %s\n", ascii_output_with_spaces);
}
return 0;
}
代码解释
- 函数参数:
hexstr_to_asciistr接收一个十六进制字符串、一个用于存储结果的缓冲区,以及缓冲区的大小,缓冲区大小参数是防止缓冲区溢出(Buffer Overflow)的关键安全措施。 - 有效性检查:检查输入指针是否为
NULL,以及缓冲区大小是否为0。 - 长度检查:一个字节由两个十六进制字符表示,所以输入字符串的长度必须是偶数,结果字符串的长度是输入长度的一半,必须小于输出缓冲区的大小。
- 循环转换:
for循环步长为2,每次处理两个字符。 tolower:将字符统一转换为小写,这样无论是'A'还是'a'都能被正确处理。- 有效性检查:再次检查这两个字符是否是合法的十六进制字符(
0-9,a-f)。 - 字符转数值:这是核心步骤。
- 如果字符在
'a'到'f'之间,它的值就是字符 - 'a' + 10。 - 如果字符在
'0'到'9'之间,它的值就是字符 - '0'。
- 如果字符在
- 组合字节:
high_val << 4将高4位移动到正确的位置, 按位或运算将低4位合并进来。 - 存入结果:将组合好的
unsigned char存入结果数组。 - 结束符:循环结束后,手动在结果字符串的最后添加
\0。 main函数:展示了如何调用此函数,并处理了一个带有空格的输入(通常需要先去除空格再进行转换)。
十六进制数值转ASCII字符
这个操作相对简单,就是将一个数值(0-255)强制类型转换为 char,这个 char 就是它对应的ASCII字符。
核心思路
直接将一个表示十六进制数值的整数(如 0x48)赋值给一个 char 类型的变量。
示例代码
#include <stdio.h>
int main() {
// 定义一个整型变量,用十六进制赋值
int hex_value = 0x48; // 十进制的72
int hex_value_2 = 0x6F; // 十进制的111
// 将整型变量强制转换为 char 类型
// 在ASCII码表中,72对应'H',111对应'o'
char ascii_char = (char)hex_value;
char ascii_char_2 = (char)hex_value_2;
printf("十六进制数值 0x%x 对应的ASCII字符是: '%c'\n", hex_value, ascii_char);
printf("十六进制数值 0x%x 对应的ASCII字符是: '%c'\n", hex_value_2, ascii_char_2);
// 也可以直接将十进制数值转换
char another_char = (char)65; // ASCII码65是 'A'
printf("十进制数值 65 对应的ASCII字符是: '%c'\n", another_char);
return 0;
}
代码解释
int hex_value = 0x48;:这里定义了一个整型变量hex_value,并给它赋了一个十六进制值0x48,在内存中,它存储的就是数字72。char ascii_char = (char)hex_value;:这是一个类型转换,它将int类型的72截断为char类型,因为72在char的可表示范围内(-128到127),所以转换后ascii_char的值就是72。printf(..., '%c', ...):%c是printf的格式化字符,它会将一个数值解释为ASCII码并打印出对应的字符。72被打印成了'H'。
| 场景 | 输入 | 输出 | 核心方法 |
|---|---|---|---|
| 字符串转换 | "48656C6C6F" |
"Hello" |
逐字符解析,计算数值,存入新字符串。 |
| 数值转换 | 0x48 (整数) |
'H' (字符) |
类型转换 (char)0x48。 |
在实际编程中,操作一(字符串转换) 的应用远比操作二更普遍,请务必注意字符串转换时的缓冲区大小检查,以避免程序出现严重的安全漏洞。

(图片来源网络,侵删)
