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

如何将包含动态分配数组的结构体写入二进制文件?

你踩了C语言动态结构体序列化的经典坑!

这段代码的问题很明确:结构体里的dynamicArray是个指针,它存的只是内存里的地址,不是数组里的实际元素。当你用fwrite直接把整个结构体丢进文件时,只会把id和这个地址值写进去——64位系统下int占4字节,指针占8字节,加上结构体对齐补到16字节,所以文件大小刚好是16字节,完全没把那100个int元素写入。更糟的是,就算之后你把这个结构体读回来,那个指针地址在新的进程里根本无效,根本访问不到原来的数组内容。

正确的做法:分两步写入数据

要把带动态数组的结构体完整存进文件,得拆成几个步骤来:

  1. 先写结构体里的固定数据(比如id),再写入数组的长度(这很关键,不然读的时候不知道要分配多大内存),最后把数组的实际元素写进去。
  2. 读取的时候反过来:先读固定数据,再读数组长度,分配对应大小的内存,最后把元素读到新分配的数组里。

下面是修改后的完整代码,包含写入和读取的示例:

写入文件的完整代码

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

struct SomeStruct{
    int id;
    int* dynamicArray;
    int arrayLength; // 新增字段:记录数组长度,方便后续读取
};

int main(){
    struct SomeStruct test;
    test.id = 5;
    test.arrayLength = 100; // 明确数组的元素个数
    // 给动态数组分配内存
    test.dynamicArray = malloc(sizeof(int)*test.arrayLength);
    if (!test.dynamicArray) {
        perror("Failed to allocate memory for array");
        return 1;
    }

    // 给数组赋值(做测试用,实际场景根据需求填充)
    for(int i=0; i<test.arrayLength; i++){
        test.dynamicArray[i] = i;
    }

    // 打开文件准备写入
    FILE* handle = fopen("data", "wb");
    if(!handle){
        perror("Failed to open file for writing");
        free(test.dynamicArray);
        return 1;
    }

    // 1. 写入固定字段:id和数组长度
    fwrite(&test.id, sizeof(test.id), 1, handle);
    fwrite(&test.arrayLength, sizeof(test.arrayLength), 1, handle);
    // 2. 写入动态数组的实际元素
    fwrite(test.dynamicArray, sizeof(int), test.arrayLength, handle);

    // 收尾工作:关闭文件+释放内存
    fclose(handle);
    free(test.dynamicArray);
    return 0;
}

读取文件的完整代码(供你验证用)

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

struct SomeStruct{
    int id;
    int* dynamicArray;
    int arrayLength;
};

int main(){
    struct SomeStruct test;
    // 打开文件准备读取
    FILE* handle = fopen("data", "rb");
    if(!handle){
        perror("Failed to open file for reading");
        return 1;
    }

    // 1. 读取固定字段:id和数组长度
    fread(&test.id, sizeof(test.id), 1, handle);
    fread(&test.arrayLength, sizeof(test.arrayLength), 1, handle);
    // 2. 根据读取到的长度分配内存
    test.dynamicArray = malloc(sizeof(int)*test.arrayLength);
    if (!test.dynamicArray) {
        perror("Failed to allocate memory for array");
        fclose(handle);
        return 1;
    }
    // 3. 读取动态数组的元素
    fread(test.dynamicArray, sizeof(int), test.arrayLength, handle);

    // 验证读取结果(可选)
    printf("Read id: %d\n", test.id);
    printf("First 5 elements of array: ");
    for(int i=0; i<5; i++){
        printf("%d ", test.dynamicArray[i]);
    }
    printf("\n");

    // 收尾工作
    fclose(handle);
    free(test.dynamicArray);
    return 0;
}
几个关键注意点
  • 绝对不要直接写入指针:指针只是内存地址,换个进程甚至同一进程重启后这个地址就没用了,必须写入指针指向的实际数据。
  • 一定要记录数组长度:写入时存下数组长度,读取时才能准确分配内存,不然根本不知道要读多少元素。
  • 内存管理不能忘:动态分配的内存不管是写入还是读取后,都要记得用free释放,避免内存泄漏。
  • 加上错误检查:文件打开、内存分配都可能失败,加上perror的错误提示,调试起来会方便很多。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 12:10:51