You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

C语言中如何将十六进制char数组转换为uint8_t数组?

把十六进制字符串转成uint8_t数组的几种方法

嘿,这个问题我做嵌入式开发的时候经常碰到!其实C语言里有不少靠谱的方案能搞定这个转换,我给你详细拆解一下:

1. 用标准库sscanf快速实现

这是最省心的方法,利用sscanf的格式符直接把两位十六进制字符转成一个uint8_t字节。关键是用%2hhx这个格式:

  • %x:表示读取十六进制数
  • hh:指定把结果存储到unsigned char(也就是uint8_t)类型的变量里
  • 2:限制每次最多读两个字符,刚好对应一个字节的两位十六进制

示例代码:

#include <stdio.h>
#include <stdint.h>
#include <string.h>

int main() {
    const char hex_str[] = "DABC95C1";
    size_t str_len = strlen(hex_str);
    
    // 先校验字符串长度:必须是偶数,不然没法两两组成字节
    if (str_len % 2 != 0) {
        printf("Error: 十六进制字符串长度必须是偶数!\n");
        return 1;
    }
    
    size_t byte_count = str_len / 2;
    uint8_t byte_arr[byte_count];
    
    // 循环读取每两个字符,转成一个字节
    for (size_t i = 0; i < byte_count; i++) {
        sscanf(&hex_str[i*2], "%2hhx", &byte_arr[i]);
    }
    
    // 验证结果
    for (size_t i = 0; i < byte_count; i++) {
        printf("0x%02X ", byte_arr[i]);
    }
    printf("\n"); // 输出会是:0xDA 0xBC 0x95 0xC1
    return 0;
}

2. 用strtol实现转换

如果你习惯用strtol处理字符串转数字,也可以用这个方法:每次截取两位字符存到临时数组,转成long后再强制转换成uint8_t(因为两位十六进制最大是0xFF,不会超出long范围)。

示例代码:

#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>

int main() {
    const char hex_str[] = "DABC95C1";
    size_t str_len = strlen(hex_str);
    
    if (str_len % 2 != 0) {
        printf("Error: 十六进制字符串长度必须是偶数!\n");
        return 1;
    }
    
    size_t byte_count = str_len / 2;
    uint8_t byte_arr[byte_count];
    
    for (size_t i = 0; i < byte_count; i++) {
        char temp[3] = {0}; // 要留一个位置存字符串结束符'\0'
        strncpy(temp, &hex_str[i*2], 2);
        // 以16进制转成long,再强制转成uint8_t
        byte_arr[i] = (uint8_t)strtol(temp, NULL, 16);
    }
    
    // 验证结果
    for (size_t i = 0; i < byte_count; i++) {
        printf("0x%02X ", byte_arr[i]);
    }
    printf("\n");
    return 0;
}

3. 手动实现转换(适合无标准库场景或追求性能)

如果是在嵌入式环境里没有标准库可用,或者想自己控制转换逻辑,可以手动实现。核心思路是:每个十六进制字符对应4位二进制,两个字符拼成8位字节——第一个字符是高4位(左移4位),第二个是低4位,按位或起来就是目标字节。

示例代码:

#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <ctype.h>

// 单个十六进制字符转成4位数值
static uint8_t hex_char_to_val(char c) {
    c = toupper(c); // 统一转大写,兼容小写输入
    if (c >= '0' && c <= '9') {
        return c - '0';
    } else if (c >= 'A' && c <= 'F') {
        return 10 + (c - 'A');
    }
    // 遇到非法字符可以返回错误,这里简单返回0
    return 0;
}

// 十六进制字符串转uint8_t数组
void hex_str_to_uint8(const char* hex_str, uint8_t* byte_arr, size_t byte_count) {
    for (size_t i = 0; i < byte_count; i++) {
        // 高4位左移4位,低4位直接取,按位或合并
        byte_arr[i] = (hex_char_to_val(hex_str[i*2]) << 4) | hex_char_to_val(hex_str[i*2 + 1]);
    }
}

int main() {
    const char hex_str[] = "DABC95C1";
    size_t str_len = strlen(hex_str);
    
    if (str_len % 2 != 0) {
        printf("Error: 十六进制字符串长度必须是偶数!\n");
        return 1;
    }
    
    size_t byte_count = str_len / 2;
    uint8_t byte_arr[byte_count];
    
    hex_str_to_uint8(hex_str, byte_arr, byte_count);
    
    // 验证结果
    for (size_t i = 0; i < byte_count; i++) {
        printf("0x%02X ", byte_arr[i]);
    }
    printf("\n");
    return 0;
}

几个需要注意的点:

  • 字符串长度校验:一定要确保输入的十六进制字符串长度是偶数,不然最后一个字符没法组成完整的字节,会导致转换错误。
  • 大小写兼容:标准库函数默认支持大小写的十六进制字符(比如daDA都能转成0xDA),手动实现的话记得用touppertolower统一处理。
  • 非法字符处理:如果输入包含非十六进制字符(比如G、@等),标准库函数会停止转换或忽略非法部分,手动实现时可以加额外的判断逻辑来抛出错误。

内容的提问来源于stack exchange,提问作者vicR

火山引擎 最新活动