Это тестовая программа, которую я написал для более крупного проекта, над которым я работаю.Это связано с записью данных структуры на диск с помощью 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 () не должен писать только адрес, который содержит имя (то есть адрес начала строки)?То есть я передаю sizeof (struct Person) в fwrite (), и все же он записывает строку, на которую указывает 'name'.
Еще больше меня смущает поведение fread ().Опять же, если я передаю sizeof (struct Person), как читается фактическое значение name?Как распределяется память для него?
Мое предыдущее понимание того, как использовать fwrite () + fread (), заключалось в том, что мне пришлось бы «вручную» записывать данные, на которые указывал «имя», ««читать» эти данные вручную, а затем скопировать эту строку после выделения памяти для структуры и члена name.Другими словами, мне пришлось бы самостоятельно обходить любые указатели, записывать данные, а затем считывать эти данные обратно в том же порядке.
РЕДАКТИРОВАТЬ : Дэн и другие правы.Я посмотрел на выходной файл с xxd:
0000000: 1600 0000 0000 0000 30a0 d900 0000 0000 ........0.......
Если я распечатываю адрес, который содержит имя, перед записью и после прочтения он тот же (0xd9a030), который совпадает с выводом из xxd.