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

含内部结构体指针的结构体如何单次用fwrite/fread读写二进制文件

C语言含动态指针的结构体二进制单次读写解决方案

问题背景

在C语言中处理结构体的二进制文件读写时,两种结构体的表现存在明显差异:

  • 含固定Point数组的Path_array结构体,直接用fwrite()/fread()单次读写整个结构体即可正常工作。
  • 含Point指针的Path_pointer结构体,直接读写结构体本身会失败,最初怀疑是fwrite()/fread()的第二个参数设置问题,但实际原因并非如此。

失败原因

Path_array中的数组是结构体的一部分,内存地址连续,因此单次写入整个结构体时,数组的所有数据会被一并写入文件;而Path_pointer中的指针仅存储了动态分配内存的地址,直接写入结构体时,只会把这个内存地址写入文件,而非指针指向的实际数据。读取时,这个地址在当前进程中无效,导致无法正确恢复数据。

正确单次读写方法

要实现含动态指针结构体的单次二进制读写,需要将结构体的元数据(如数据长度)和指针指向的实际数据合并为连续的内存块进行操作:

  1. 写入时:把结构体的固定字段(如长度)和指针指向的数据拷贝到一块连续临时内存,再一次性写入文件。
  2. 读取时:先读取元数据(长度),根据长度分配对应内存,再一次性读取数据到分配好的内存中。

示例代码

首先定义基础结构体:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct {
    int x;
    int y;
} Point;

// 含固定数组的结构体(可直接单次读写)
typedef struct {
    int len;
    Point points[100];
} Path_array;

// 含动态指针的结构体(需特殊处理)
typedef struct {
    int len;
    Point *points;
} Path_pointer;

写入含指针的结构体(单次操作)

int write_path(FILE *fp, const Path_pointer *path) {
    if (!fp || !path || !path->points) return -1;

    // 计算总数据大小:长度字段 + 所有Point数据
    size_t total_size = sizeof(path->len) + path->len * sizeof(Point);
    char *buf = malloc(total_size);
    if (!buf) return -1;

    // 将长度和数据拷贝到连续内存
    memcpy(buf, &path->len, sizeof(path->len));
    memcpy(buf + sizeof(path->len), path->points, path->len * sizeof(Point));

    // 单次写入所有数据
    size_t written = fwrite(buf, 1, total_size, fp);
    free(buf);

    return written == total_size ? 0 : -1;
}

读取含指针的结构体(单次操作)

int read_path(FILE *fp, Path_pointer *path) {
    if (!fp || !path) return -1;

    // 先读取长度字段
    size_t read_len = fread(&path->len, sizeof(path->len), 1, fp);
    if (read_len != 1) return -1;

    // 根据长度分配内存
    path->points = malloc(path->len * sizeof(Point));
    if (!path->points) return -1;

    // 单次读取所有Point数据
    size_t read_data = fread(path->points, sizeof(Point), path->len, fp);
    return read_data == path->len ? 0 : -1;
}

与其他相关帖子的区别

  • 本方案针对动态内存分配的结构体,解决了单次读写的核心需求,而非逐个元素操作。
  • 其他相关帖子大多未给出基于fwrite()/fread()的完整单次读写解决方案,要么仅讨论问题原因,要么采用逐元素读写的方式,无法满足一次性读写的需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 23:42:51