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

使用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 11:29:48