This is a test program that I wrote for a larger project that I am working on. This involves writing structure data to disk using the fwrite () function, and then reading this data using fread (). One member of the structure is dynamically allocated.
Firstly, here is my code
#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; }
And outpout
22 Name that is really, really, really, really, really, really, long.
My question is: why does this work? Shouldn't fwrite () write only the address that contains the "name" (ie, the address of the beginning of the line)? That is, I pass sizeof (struct Person) to fwrite (), and yet it writes the line pointed to by 'name'.
Even more confusing for me is the behavior of fread (). Again, if I pass sizeof (struct Person), how is the actual value of the "name" read? How is memory allocated for him?
My previous understanding of how to use fwrite () + fread () was that I would have to "manually" write the data pointed to by "name", "read" this data manually, and then copy this line after highlighting memory for both the structure and the member 'name'. In other words, I would have to go through any pointers, write the data, and then read this data in the same order.
EDIT : Dan and the others are true. I looked at the output file using xxd:
0000000: 1600 0000 0000 0000 30a0 d900 0000 0000 ........0.......
If I print the address that 'name' contains before writing and after reading, the same (0xd9a030), which corresponds to the output from xxd.