Write to file struct containing char pointer

Writing to file a struct containing a dynamically allocated char* pointer

Let’s say we have this struct

struct MyData {
    char* name;
    int value;
};

Initializing it as a normal struct (not pointer to a struct) and printing the values

int main() {	
    MyData data;
    /* we allocate memory for the string */
    data.name = (char*)calloc(15, sizeof(char));

    /* we copy over in out struct a string */
    strcpy(data.name, "struct test");
    data.value = 20;

    printf("%s %d\n", data.name, data.value);

It produces the following output

struct test 20

But since it contains char* name and not something like char name[100] we can’t simply write

fwrite(data, sizeof(MyData), 1, file);

Because the text value char* name points to won’t be saved to file.

Instead we will write each value individually. To tell fwrite not to write the pointer but the text value it points to, we first use (&data) to take it’s memory address then use the arrow operator on it to access the “text” element. This trick gives us a pointer (which stores the address where the string is stored, which is exactly what fwrite wants). After we fwrite the int value, by passing as well it’s address.

fwrite((&data)->name, 15 * sizeof(char), 1, file);
fwrite(&data.value, sizeof(int), 1, file);

Full code is

int main() {	
    MyData data;
    data.name = (char*)calloc(15, sizeof(char));
    strcpy(data.name, "struct test");
    data.value = 20;

    FILE* file = fopen("struct.dat", "wb");
    if (file == 0) {
	printf("File could not be opened. That's why it crashes.");
    }

    /* write test */
    fwrite((&data)->name, 15 * sizeof(char), 1, file);
    fwrite(&data.value, sizeof(int), 1, file);
    fclose(file);

    /* read test */
    MyData data2;
    data2.name = (char*)calloc(15, sizeof(char));
    FILE* file2 = fopen("struct.dat", "rb");
    if (file2 == 0) {
	printf("File could not be opened.");
    }
    fread(data2.name, 15 * sizeof(char), 1, file2);
    fread(&data2.value, sizeof(int), 1, file2);

    printf("%d %s\n", data2.value, data2.name);
    return 0;
}

But what if data is a pointer to a MyData struct?

When it comes to writing strings is simple, we can use the arrow operator directly.
To write a statically allocated value, member of a struct, by using a pointer, you first have to dereference (*data) the pointer (is like saying don’t show me the address, show me the content), use the dot . operator to get to that member variable, and in the end put an ampersand behind it because fwrite wants the reference to that variable not it’s value.

Full code is:

int main() {	
    MyData* data = (MyData*)calloc(1, sizeof(MyData));
    data->name = (char*)calloc(15, sizeof(char));
    strcpy(data->name, "pointer test");
    data->value = 14;

    FILE* file = fopen("pointerStruct.dat", "wb");
    fwrite(data->name, 15 * sizeof(char), 1, file);
    fwrite(&(*data).value, sizeof(int), 1, file);
    fclose(file);

    MyData* data2 = (MyData*)calloc(1, sizeof(MyData));
    data2->name = (char*)calloc(15, sizeof(char));
    FILE* file2 = fopen("pointerStruct.dat", "rb");
    fread(data2->name, 15 * sizeof(char), 1, file2);
    fread(&(*data2).value, sizeof(int), 1, file2);

    printf("%d %s\n", data2->value, data2->name);
    return 0;
}

All this pointing, referencing and dereferencing might make your brain melt but practice is the key to understanding. Especially in programming.

FacebookTwitterLinkedin