Понимание поведения undefined для двоичного потока с использованием fseek (файл, 0, SEEK_END) с файлом

C spec имеет интересную сноску (# 268 C11dr §7.21.3 9)

"Установка индикатора положения файла в конец файла, как и в случае с fseek(file, 0, SEEK_END), имеет поведение undefined для двоичного потока (из-за возможных завершающих нулевых символов) или для любого потока с зависящей от состояния кодировкой, которая делает не обязательно заканчиваются в начальном состоянии сдвига".

Используется ли это когда-либо к двоичным потокам, читающим файл? (как с физического устройства)

IMO, двоичный файл на диске - это просто море байтов. Мне кажется, что двоичный файл не может иметь зависящую от состояния кодировку, поскольку это двоичный файл. Я неясен по понятию "двоичные широко ориентированные потоки", и если это даже может применяться к дисковым вводам/выводам.

Я вижу, что вызов fseek(file, 0, SEEK_END) в последовательном потоке, таком как COM-порт или, может быть, stdin, может не доходить до истинного конца, поскольку конец еще не определен. Таким образом, сужение вопроса на физические файлы.


[править] Ответ: Проблема со старыми (возможно, до конца 1980-х годов). В настоящее время в 2014 году Windows, POSIT-специфические и не экзотические другие: не проблема.

@Shafik Yaghmour дает хорошую ссылку в Использование fseek и ftell для определения размера файла имеет уязвимость?. Там @Jerry Coffin обсуждает CP/M, поскольку двоичные файлы не всегда имеют точную длину. (128-байтовые записи на wiki).

Спасибо @Keith Thompson ответить за мясо ответа.

Вместе это объясняет спецификации "(из-за возможных завершающих нулевых символов)".

Ответ 1

Двоичные файлы будут представлять собой последовательности 8-битных байтов с точно заданным размером в любой системе, которую вы, скорее всего, будете использовать. Но не все системы хранят файлы таким образом, а стандарт C тщательно разработан, чтобы обеспечить переносимость систем с необычными характеристиками.

Например, соответствующая реализация C может выполняться в операционной системе, которая хранит файлы в виде последовательностей 512-байтовых блоков без указания того, сколько байтов последнего блока значимо. В такой системе, когда создается двоичный файл, ОС может заполнить остаток последнего блока нулевыми байтами. Когда вы читаете из такого файла, байты заполнения могут либо появляться на входе (даже если они никогда не были явно записаны в файл), либо они могут быть проигнорированы (даже если программа, которая создала файл, могла писать их явно).

Если вы читаете из потока, недоступного для поиска (например, ввод с клавиатуры), то fseek(file, 0, SEEK_END) не просто даст вам плохой результат, он будет показывать отказ, возвращая ненулевой результат. (В POSIX-совместимых системах он возвращает -1 и устанавливает errno; ISO C этого не требует.)

В большинстве систем fseek(file, 0, SEEK_END) в двоичном файле будет либо искать фактический конец файла (позиция, определяемая точно количеством байтов в файле), либо возвращать четкую индикацию отказа. Если вы все равно используете POSIX-специфические функции, вы можете смело предположить это поведение; вы, вероятно, можете сделать то же предположение для Windows и ряда других систем. Если вы хотите, чтобы ваш код был на 100% переносимым в экзотические системы, вы не должны предполагать, что двоичные файлы не будут дополняться дополнительными нулевыми байтами.