Search code examples
c++binary

Using reinterpret_cast<> to write in binary to a file


Foo program[] {...};

ofstream ofs{file_path, std::ios::binary};

if (ofs) {
   ofs.write(reinterpret_cast<char*>(program), sizeof(program));
   ofs.close();
}

I've seen examples of reinterpret_cast<char*> being used to write to a file like this. Is this bad usage?

From what I know, the resulting pointer isn't guaranteed to be at the same memory address, but since we're not using the resulting pointer, is it still bad style?


Solution

  • From what I know, the resulting pointer isn't guaranteed to be at the same memory address

    The pointer is guaranteed to represent the same address as the address of program and it is guaranteed to point to program.

    While there are some technicalities that currently mean that access (or pointer arithmetic) through this pointer isn't well-defined according to the C++ standard if being strict about its interpretation, that has no relevance in practice and is purely a defect in the standard. The behavior is exactly as expected in practice:

    ofs.write(reinterpret_cast<char*>(program), sizeof(program));
    

    will write the object representation of program into the stream.

    The problem with this is not undefined behavior or anything like that, but semantics: It is usually a bad idea to write object representations of objects into a file, because when you attempt to read it back, it will only work correctly if the system/program reading it back use the exact same representations (e.g. endianess) for types and the exact same class layout (which can for example depend on ABI).

    If Foo is not a trivially-copyable type, then it is even completely wrong to write the object representation of Foo into the file, because the object representation would not correspond to the full value/state of the object at all. Consider for example std::string which holds a pointer to dynamically-allocated memory. If you copy only the pointer via the object representation, then you haven't copied the state of that allocated memory at all.

    It is almost always a much safer approach to properly serialize the object into the file by defining a fixed system-independent file format and representation for each value and then writing each value (instead of object representation) according to that protocol into the file.