Это тестовая программа, которую я написал для большого проекта, над которым я работаю. Это связано с записью данных структуры на диск с помощью fwrite () и последующим чтением этих данных с помощью 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;
}
И вывод
22 Name that is really, really, really, really, really, really, long.
У меня вопрос, почему это работает? Разве 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.......
Если я распечатаю адрес, который 'name' содержит до записи, и после чтения, он будет таким же (0xd9a030), что соответствует выходным данным из xxd.