The portrayal of this as a C vs C++ thing is misleading. C++ provides std::fwrite(const void*, ...)
just like C. Where C++ chooses to be more defensive is specifically the std::iostream
versions.
"Almost in all cases the binary data to be written to files is not char array"
That's debatable. In C++ isn't not unusual to add a level of indirection in I/O, so objects are streamed or serialised to a convenient - and possibly portable (e.g. endian-standardised, without or with standardised structure padding) - representation, then deserialised/parsed when re-read. The logic is typically localised with the individual objects involved, such that a top-level object doesn't need to know details of the memory layout of its members. Serialisation and streaming tends to be thought of / buffered etc. at the byte level - fitting in better with character buffers, and read()
and write()
return a number of characters that could currently be transmitted - again at the character and not object level - so it's not very productive to pretend otherwise or you'll have a mess resuming partially successful I/O operations.
Raw binary writes / reads done naively are a bit dangerous as they don't handle these issues so it's probably a good thing that the use of these functions is made slightly harder, with reinterpret_cast<>
being a bit of a code smell / warning.
That said, one unfortunate aspect of the C++ use of char*
is that it may encourage some programmers to first read to a character array, then use inappropriate casts to "reinterpret" the data on the fly - like an int*
aimed at the character buffer in a way that may not be appropriately aligned.
If you want to print a stream of characters, you could use operator<<()
. Isn't write()
method designed for writing raw data?
To print a stream of characters with operator<<()
is problematic, as the only relevant overload takes a const char*
and expects a '\0'
/NUL-terminated buffer. That makes it useless if you want to print one or more NULs in the output. Further, when starting with a longer character buffer operator<<
would often be clumsy, verbose and error prone, needing a NUL
swapped in and back around the streaming, and would sometimes be a significant performance and/or memory use issue e.g. when writing some - but not the end - of a long string literal into which you can't swap a NUL, or when the character buffer may be being read from other threads that shouldn't see the NUL.
The provided std::ostream::write(p, n)
function avoids these problems, letting you specify exactly how much you want printed.