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

fread读取二进制文件异常:GCC/Clang输出垃圾值,TCC正常

问题排查与正确实现

代码中的核心问题

  • 变量类型不匹配
    你用int类型n存储单字节数据,但int通常占4字节(x86/x86_64平台)。每次fread(&n,1,1,fp)只写入n的第一个字节,剩下3字节是栈上的未初始化垃圾值。GCC/Clang默认不会初始化栈变量,所以输出的是有效字节+随机垃圾的组合;TCC默认将未初始化栈变量置0,所以看起来输出正确,这只是巧合,并非代码本身正确。

  • 字节序与符号问题(fread(&n,4,1,fp)时的负数)
    JPEG文件采用大端字节序,而x86/x86_64平台是小端字节序。当你读取4字节到int时,比如JPEG头的0xFF 0xD8,会被解析为0xD8FF0000(若后续字节为0),作为有符号int,最高位为1时会被解释为负数。

  • 缺少错误检查
    代码未检查fopen的返回值,如果文件路径错误或权限不足,fp会是NULL,后续fread会触发未定义行为。

正确的fread读取二进制文件实现

改用unsigned char存储单字节数据,同时添加必要的错误检查:

#include <stdio.h>

int main()
{
    FILE *fp = fopen("/home/lovelorn/Pictures/post-3.jpeg", "rb");
    if (fp == NULL) {
        perror("Failed to open file");
        return 1;
    }

    unsigned char byte;
    for (int i = 0; i < 100; i++) {
        // 检查读取是否成功
        size_t read_count = fread(&byte, 1, 1, fp);
        if (read_count != 1) {
            // 读取失败或到文件末尾
            break;
        }
        // 以无符号十进制输出,范围0-255
        printf("%u\n", byte);
    }

    fclose(fp);
    return 0;
}

关键要点

  • 读取单字节二进制数据时,优先用unsigned char,避免符号扩展和未初始化字节的问题。
  • 始终检查fopen的返回值,防止空指针操作。
  • 检查fread的返回值,处理读取失败或文件提前结束的情况。
  • 如果需要读取多字节数据(比如JPEG的16位长度字段),要手动处理字节序转换,比如将大端转为小端:
    // 读取2字节大端数据转为uint16_t
    unsigned char buf[2];
    fread(buf, 1, 2, fp);
    uint16_t value = (buf[0] << 8) | buf[1];
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 03:06:17