C fread()神奇地读取动态分配的struct成员,怎么样?

tsl*_*kan 7 c struct fwrite fread

这是我为一个我正在研究的大型项目编写的测试程序.它与使用fwrite()将struct数据写入磁盘然后用fread()读取该数据有关.结构的一个成员是动态分配的.

首先,这是我的代码

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

#define STRING_LEN  128

struct Person {
    int age;
    char *name;
};

int main(int argc, const char *argv[])
{
    struct Person *person = calloc(1, sizeof(struct Person));
    person->age = 22;
    person->name = calloc(STRING_LEN, sizeof(char));

    char *name = "Name that is really, really, really, really, really, really, long.";
    strncpy(person->name, name, STRING_LEN);

    FILE *out_file = fopen("rw.out", "w");
    fwrite(person, sizeof(struct Person), 1, out_file);
    fclose(out_file);

    FILE *in_file = fopen("rw.out", "r");
    struct Person *person_read = calloc(1, sizeof(struct Person));
    fread(person_read, sizeof(struct Person), 1, in_file);
    fclose(in_file);

    printf("%d %s\n", person_read->age, person_read->name);

    free(person->name);
    free(person);
    free(person_read);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

和outpout

22 Name that is really, really, really, really, really, really, long.
Run Code Online (Sandbox Code Playgroud)

我的问题是,为什么这有效?不应该fwrite()只写'name'包含的地址(即字符串开头的地址)?也就是说,我将sizeof(struct Person)传递给fwrite(),但它正在编写'name'指向的字符串.

对我来说更令人困惑的是fread()的行为.同样,如果我传递的是sizeof(struct Person),那么'name'的实际值是如何被读取的?如何分配内存?

我之前对如何使用fwrite()+ fread()的理解是,我必须"手动"写入'name'指向的数据,"手动"读取该数据,然后在分配内存后复制该字符串结构和'名称'成员.换句话说,我必须自己遍历任何指针,写入数据,然后以相同的顺序读回数据.

编辑:丹和其他人是正确的.我用xxd查看了输出文件:

0000000: 1600 0000 0000 0000 30a0 d900 0000 0000  ........0.......
Run Code Online (Sandbox Code Playgroud)

如果我在写入之前打印出'name'包含的地址,并且在读取之后它是相同的(0xd9a030),它与xxd的输出相匹配.

Dan*_*Dan 10

您正在结构中写入数据,该结构是一个int,后跟一个指向字符串的指针.它就像其他任何数据一样,你知道它有多长,因为结构是固定长度的 - 一个int加一个指针.您读取与原始名称字符串相同的指针.名称本身既不是书面也不是读书.


Joh*_*ode 6

双方person->nameperson_read->name拉闸指向同一个内存位置.由于在重新person->name读取文件之前未释放,因此指针值person_read->name仍然有效.

如果您person->name已从其他程序释放或读取该文件,则指针值将不再有效,并且尝试引用它将调用未定义的行为 - 您将打印出乱码或得到段错误.