使用fread读取十六进制二进制文件时字节交换问题求助
问题根源:字节序(Endianness)差异
你遇到的是典型的字节序不匹配问题,咱们一步步拆解清楚:
你的二进制文件内容是十六进制 00 00 19 00,这是大端字节序的存储逻辑——高位字节放在文件的前面,低位字节在后。对应4字节整数的话,实际值是 0x00001900,转十进制就是 6400。
但你的主机系统(大概率是x86/x86_64架构)用的是小端字节序——低位字节存在内存的低地址,高位字节存在高地址。当你用fread直接把文件字节读入int变量时,字节顺序被反转了:
- 文件里的字节顺序:
00(高字节)→00→19→00(低字节) - 被小端系统解析后,变成了
0x00190000,十进制就是163840,这就是你看到的“字节交换”现象。
解决方案
这里有几种可靠的解决方法,按需选择:
1. 用标准库的字节序转换函数
如果你的系统支持POSIX标准,直接用ntohl()函数(Network to Host Long)最方便——网络字节序默认是大端,这个函数能把大端字节序的32位整数转成主机字节序的整数。
修改后的代码如下:
#include <stdio.h> #include <stdlib.h> #include <arpa/inet.h> // 包含ntohl的头文件 int main(int argc, char *argv[]) { if (argc < 2) { printf("Usage: %s <file_path>\n", argv[0]); return EXIT_FAILURE; } FILE *fp = fopen(argv[1], "rb"); if (fp == NULL) { printf("Error - Failed opening the file\n"); return EXIT_FAILURE; } else { printf("Disk image file [%s] opened...\n\n", argv[1]); } uint32_t x; // 用无符号32位整数更安全,避免符号位干扰 fread(&x, sizeof(uint32_t), 1, fp); uint32_t corrected_value = ntohl(x); // 转换字节序 printf("Block count Hex: %x\n", corrected_value); printf("Block count dec: %u\n", corrected_value); fclose(fp); return EXIT_SUCCESS; }
2. 手动字节交换(跨平台兼容)
如果你的系统不支持POSIX函数,就手动读取每个字节再重新组合:
#include <stdio.h> #include <stdlib.h> int main(int argc, char *argv[]) { if (argc < 2) { printf("Usage: %s <file_path>\n", argv[0]); return EXIT_FAILURE; } FILE *fp = fopen(argv[1], "rb"); if (fp == NULL) { printf("Error - Failed opening the file\n"); return EXIT_FAILURE; } else { printf("Disk image file [%s] opened...\n\n", argv[1]); } unsigned char bytes[4]; fread(bytes, sizeof(unsigned char), 4, fp); // 按大端规则组合:第一个字节是最高位,最后一个是最低位 uint32_t corrected_value = (bytes[0] << 24) | (bytes[1] << 16) | (bytes[2] << 8) | bytes[3]; printf("Block count Hex: %x\n", corrected_value); printf("Block count dec: %u\n", corrected_value); fclose(fp); return EXIT_SUCCESS; }
3. 验证主机字节序(可选)
如果你想确认自己的系统是大端还是小端,可以加这段测试代码:
void check_endianness() { uint32_t test = 0x00000001; unsigned char *byte = (unsigned char *)&test; if (byte[0] == 1) { printf("System is little-endian\n"); } else { printf("System is big-endian\n"); } }
运行修改后的代码,你就能得到正确结果:Block count Hex: 1900,Block count dec: 6400。
内容的提问来源于stack exchange,提问作者Daniel Olaya
相关产品推荐
相关产品推荐

