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
相关产品推荐
相关产品推荐

