Почему fseek или fflush всегда требуется между чтением и записью в режимах обновления?

Q: Я пытаюсь обновить файл на месте, используя режим fopen "r+", читая определенную строку и записывая измененную строку, но это не работает.

A: Обязательно вызовите fseek перед тем, как писать, и для поиска возврата к началу строки, которую вы пытаетесь перезаписать, и потому что fseek или fflush всегда требуются между чтением и записью в режимах чтения/записи "+". ,

Мой вопрос заключается в том, почему fseek или fflush всегда требуются между чтением и записью в режимах чтения/записи "+"? Раздел 5.2 Эндрю Кенига C Traps and Pitfalls (1989) упоминал, что это связано с проблемой обратной совместимости. Кто-нибудь может объяснить подробно?

Ответ 1

Библиотека буферизует операции ввода и вывода. Посмотрите setvbuf() и параметры _IOFBF, _IOLBF для этой функции.

fseek() или fflush() требуют, чтобы библиотека выполняла буферизованные операции.

Стандарт определяет операцию поиска или сброса как обязательную, чтобы позволить библиотеке некоторые сочетания клавиш; в противном случае для каждой операции ввода-вывода библиотека должна была бы проверить, была ли предыдущая операция также операцией чтения (или операцией записи), и инициировать сброс самостоятельно, если изменилось "направление" ввода-вывода. Имея спецификации как есть, библиотека может предположить, что клиент выполнил поиск/сброс перед изменением направления ввода/вывода.

Ответ 2

Потому что он упрощает код ОС/библиотеки. Файловый поток может иметь отдельные буферы чтения и записи, и для обеспечения их синхронизации всегда требуется дополнительное усилие. Это стоило бы производительности в разы, когда это не было необходимо.

Поэтому вместо этого программисту необходимо сделать это явно, когда это необходимо.

Ответ 3

Прочтите Plauger " Стандартную библиотеку C ", чтобы узнать, почему различные функции стандартной библиотеки (C89) являются такими, какие они есть, и, в частности, почему части стандартной библиотеки ввода-вывода являются такими, какие они есть. Одна из причин заключается в том, что C работает в самых разных системах и с разными средами; устройства, такие как ленты, вполне могут нуждаться в обработке, отличной от той, с которой вы привыкли думать. Кроме того, в Unix рассмотрим ваше "tty" устройство - оно соединяет клавиатуру и мышь с экраном - три совершенно разных аппаратных элемента. Координация между ними достаточно сложна; правила в стандарте делают это проще.


Обратите внимание, что стандарт обязывает это. Это из стандарта C11, ISO/IEC 9899: 2011, но формулировка была аналогичной в предыдущих выпусках:

§7.21.5.3 Функция fopen

¶7 Когда файл открывается с режимом обновления ("+" в качестве второго или третьего символа в приведенном выше списке значений аргументов режима), ввод и вывод могут выполняться в связанном потоке. Однако выход не должен быть непосредственно с последующим вводом без промежуточного вызова к fflush функции или к функции позиционирования файла (fseek, fsetpos или rewind), а вход не должен быть непосредственно с последующим выходом без промежуточного вызова на позиционирование файла функция, если операция ввода не встречает конец файла. Открытие (или создание) текстового файла в режиме обновления может вместо этого открыть (или создать) двоичный поток в некоторых реализациях.