Ответ 1
Отображение этого как объекта C vs С++ вводит в заблуждение. С++ предоставляет std::fwrite(const void*, ...)
, как и C. Где С++ предпочитает быть более защитным, в частности версии std::iostream
.
"Почти во всех случаях двоичные данные, которые должны быть записаны в файлы, не являются char array"
Это спорно. В С++ нет ничего необычного, чтобы добавить уровень косвенности в I/O, поэтому объекты передаются потоком или сериализуются в удобную и, возможно, переносимую (например, стандартизованную по стандарту, без или со стандартным дополнением структуры) - представление, затем десериализованное/анализируется при повторном чтении. Логика обычно локализована с участием отдельных объектов, так что объекту верхнего уровня не нужно знать детали расположения макетов своих членов. Сериализация и потоковая передача, как правило, считаются/буферизованы и т.д. На уровне байтов - лучше подходят для буферов символов, а read()
и write()
возвращают несколько символов, которые в настоящее время могут быть переданы, - снова на символе, а не на объекте уровень - так что не очень продуктивно притворяться иначе, иначе у вас будет беспорядок, возобновляющий частично успешные операции ввода-вывода.
Необработанные двоичные записи/чтения выполняются наивно, поскольку они не справляются с этими проблемами, поэтому, вероятно, хорошо, что использование этих функций выполняется немного сложнее, при этом reinterpret_cast<>
является немного запахом кода/предупреждение.
Тем не менее, один неудачный аспект использования С++ для char*
заключается в том, что он может побудить некоторых программистов сначала прочитать массив символов, а затем использовать неулокальные приведения для "переинтерпретации" данных "на лету" - например, int*
, предназначенный для символьного буфера способом, который может быть неправильно выровнен.
Если вы хотите напечатать поток символов, вы можете использовать
operator<<()
. Не методwrite()
, предназначенный для записи необработанных данных?
Для печати потока символов с operator<<()
является проблематичным, так как единственная релевантная перегрузка занимает const char*
и ожидает буфер '\0'
/NUL-terminated. Это делает его бесполезным, если вы хотите напечатать один или несколько NUL на выходе. Кроме того, при запуске с более длинным символьным буфером operator<<
часто бывают неуклюжие, подробные и подверженные ошибкам, нуждающиеся в NUL
, обмениваемые и обратные вокруг потоковой передачи, и иногда это может быть значительная проблема с производительностью и/или памятью, например. при написании некоторого - но не конца - длинного строкового литерала, в который вы не можете поменять NUL или когда буфер символов может быть прочитан из других потоков, которые не должны видеть NUL.
Предоставленная функция std::ostream::write(p, n)
позволяет избежать этих проблем, позволяя точно указать, сколько вы хотите напечатать.