You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言文件处理问题:读取十六进制字符存入uint8_t*

解决从文件读取十六进制字符到uint8_t变量的问题

首先得说清楚,你原代码里有好几个关键问题导致了奇怪的输出和段错误,我先帮你拆解一下:

原代码的核心问题

  • 类型完全不匹配:file_handling函数声明返回int,但你在main里把它赋值给uint8_t*指针,这就相当于把一个普通数值当成内存地址用,必然会输出错误内容。
  • 野指针陷阱:output_hand指向函数内部的局部数组str,函数执行完返回后,这个局部数组会被系统回收,指针就变成了无效的野指针,后续访问完全是未定义行为。
  • 未初始化指针导致段错误:main里的uint8_t *output没有初始化,直接写*output = ...就会往随机内存地址写数据,触发段错误太正常了——你这是在瞎写内存啊!
  • 对十六进制存储的误解:你提到想把"we"作为十六进制值存入,但"we"是ASCII字符,对应的十六进制是0x77('w')和0x65('e');如果是后面说的文件内容ab fe ea ce 1d,那是每个两位字符串代表一个字节的十六进制值,比如ab对应0xab,这两种需求处理方式完全不同。

针对你实际需求的解决方案

从你后面说的文件内容(空格分隔的两位十六进制字符串)来看,你应该是想把这些文本转换成对应的字节值存在uint8_t数组里,下面是可以直接用的代码:

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

// 从文件读取空格分隔的十六进制字符串,转换为uint8_t数组
// 返回读取到的字节数,output会被分配内存,使用后要记得free
size_t read_hex_from_file(const char* filename, uint8_t** output) {
    FILE* file = fopen(filename, "r");
    if (!file) {
        printf("打不开文件,请检查路径是否正确!\n");
        return 0;
    }

    // 先预分配100字节的内存,不够再扩容
    size_t capacity = 100;
    *output = malloc(capacity * sizeof(uint8_t));
    if (!*output) {
        printf("内存分配失败!\n");
        fclose(file);
        return 0;
    }

    size_t byte_count = 0;
    char hex_pair[3]; // 存两位十六进制字符
    // 逐个读取两位十六进制字符串,自动跳过空格
    while (fscanf(file, "%2s", hex_pair) == 1) {
        uint8_t byte_val = 0;
        // 把两位字符转换成十六进制数值
        for (int i = 0; i < 2; i++) {
            char c = toupper(hex_pair[i]); // 统一转成大写,方便处理
            if (c >= '0' && c <= '9') {
                byte_val = (byte_val << 4) | (c - '0');
            } else if (c >= 'A' && c <= 'F') {
                byte_val = (byte_val << 4) | (10 + c - 'A');
            } else {
                printf("遇到无效的十六进制字符:%c\n", hex_pair[i]);
                free(*output);
                fclose(file);
                return 0;
            }
        }
        // 内存不够就扩容
        if (byte_count >= capacity) {
            capacity *= 2;
            uint8_t* temp = realloc(*output, capacity * sizeof(uint8_t));
            if (!temp) {
                printf("内存扩容失败!\n");
                free(*output);
                fclose(file);
                return 0;
            }
            *output = temp;
        }
        (*output)[byte_count++] = byte_val;
    }

    fclose(file);
    return byte_count;
}

int main() {
    uint8_t* hex_data = NULL;
    size_t count = read_hex_from_file("filename", &hex_data);

    if (count > 0 && hex_data) {
        printf("成功读取%zu个字节:\n", count);
        for (size_t i = 0; i < count; i++) {
            printf("0x%02x ", hex_data[i]);
        }
        printf("\n");
        // 用完一定要释放内存
        free(hex_data);
    }

    return 0;
}

你关心的几个问题解答

1. 为什么*output = 0xFA看似可行,但读取文件时就触发段错误?

别被表面现象骗了!uint8_t *output; *output = 0xFA;这行代码本身就是未定义行为,只是碰巧没触发段错误而已。output是未初始化的指针,指向的是随机内存地址,直接赋值可能覆盖其他程序的内存,搞不好会直接崩溃。正确的做法是要么让指针指向一个已存在的变量:

uint8_t val;
uint8_t *output = &val;
*output = 0xFA;

要么用malloc动态分配内存,像上面代码里那样。

2. fgets怎么区分普通字符和十六进制字符?

fgets根本不会区分!它只是按文本流读取字符,不管是普通字符还是十六进制字符,在它眼里都是ASCII字符。我们得自己判断读取的字符是否符合十六进制格式(0-9、a-f、A-F),然后手动转换成对应的数值。上面的代码用fscanf("%2s", hex_pair)每次读取两位字符,然后通过循环把字符转成字节值,就是干这个事的。

3. 如何正确从文件读取值存入uint8_t变量?

如果只是读取单个十六进制对(比如"ab")存到单个uint8_t变量里,可以简化代码:

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

int main() {
    FILE* file = fopen("filename", "r");
    if (!file) {
        printf("文件打开失败!\n");
        return 1;
    }

    uint8_t value;
    // 直接用fscanf读取十六进制值,%hhx对应uint8_t
    if (fscanf(file, "%hhx", &value) == 1) {
        printf("读取到的十六进制值:0x%02x\n", value);
    } else {
        printf("读取失败!\n");
    }

    fclose(file);
    return 0;
}

这里用%hhx格式符,fscanf会自动把文本里的十六进制字符串转换成uint8_t数值,比自己写转换逻辑更简单。

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:11:23