When working binary input/output, we often see/write code similar to this
in_file.read(reinterpret_cast<char *>(&obj), sizeof(obj))
out_file.write(reinterpret_cast<const char*>(&obj), sizeof(obj))
Now, is there any guarantee within the standard that these operations do not lead to undefined behavior? A clarification/explanation why it works would be appreciated.
Rational for the question:
According to cppreference (I hope I understood it correctly), casting T* to char*, unsigned char* and std::byte* and de-referencing the result should be legal. It explicitly states
AliasedType is std::byte, (since C++17) char, or unsigned char: this permits examination of the object representation of any object as an array of bytes.
Now what is not clear to me, is that sizeof(obj) part as well as "examination of the object representation as an array of bytes" imply that there is pointer arithmetic involved... which raises the question - is pointer arithmetic permitted by the standard? (In case of binary io I haven't looked at the actual implementations (they are a but unreadable to me at this point...), if there is alternative method used behind the scenes, feel free to clarify.
In case it does lead to undefined behavior, should bit_cast
to std::array
be preferred when doing binary IO?
I mean something like this:
auto binary_rep = std::bit_cast<std::array<const char, sizeof(obj)>>(obj);
out_file.write(&binary_rep[0], sizeof(obj));
for writing and
std::array<char, sizeof(obj)> binary_rep;
in_file.read(&binary_rep[0], sizeof(obj));
obj = bit_cast(binary_rep);
for reading?