C ++ использует streamoff
тип для представления смещения внутри (файлового) потока и определяется следующим образом в [stream.types]:
using streamoff = implementation-defined ;
Тип streamoff является синонимом одного из подписанных базовых целочисленных типов достаточного размера, чтобы представить максимально возможный размер файла для операционной системы. 287)
287) Обычно длинные длинные.
Это имеет смысл, поскольку позволяет выполнять поиск в больших файлах (в отличие от использования long
, ширина которого может составлять всего 32 бита).
[filebuf.virtuals] определяет basic_filebuf
функцию для поиска в файле следующим образом:
pos_type seekoff(off_type off, ios_base::seekdir way, ios_base::openmode which = ios_base::in | ios_base::out) override;
off_type
эквивалентно streamoff
, см. [iostreams.limits.pos]. Тем не менее, стандарт продолжает объяснять эффекты функции. Меня раздражает самое последнее предложение, которое требует вызова fseek
:
Эффекты : пусть
width
обозначаютa_codecvt.encoding()
. Еслиis_open() == false
илиoff != 0 && width <= 0
, то операция позиционирования не выполняется. В противном случае, еслиway != basic_ios::cur
илиoff != 0
, и если была выведена последняя операция, обновите выходную последовательность и запишите любую отмененную последовательность. Далее ищите новую позицию: еслиwidth > 0
, позвонитеfseek(file, width * off, whence)
, иначе позвонитеfseek(file, 0, whence)
.
fseek
принимает long
параметр. Если off_type
и streamoff
определены как long long
(как предложено стандартом), это может привести к понижающему преобразованию long
при вызове fseek(file, width * off, whence)
(что может привести к потенциально трудным для диагностики ошибкам). Это ставит под сомнение все основания для введения streamoff
типа во-первых.
Это намеренно или дефект в стандарте?
seekoff
обязательно использованияfseek
под капотом. Скорее, (предположительно знакомое?) Поведениеfseek
используется, чтобы объяснить, чтоseekoff
делает.fseek
если она делает что-то с тем же эффектом. Ноfseek
со смещением, меньшимLONG_MIN
или большим, чемLONG_MAX
не имеет значения, поэтому объяснение в лучшем случае неполное, по крайней мере для реализаций, гдеstreamoff
оно ширеlong
.Ответы:
Я думаю, что вывод, который вы делаете из этого, что существует несоответствие между потоками C ++ и
fseek
это приведет к ошибкам во время выполнения, неверен. Ситуация вроде бы:В системах, где
long
64 бита,streamoff
определяется какlong
, иseekoff
функция вызываетсяfseek
.В системах, где
long
32-разрядная версия, но ОС поддерживает 64-разрядные смещения файлов,streamoff
определяется какlong long
иseekoff
вызывает функцию, называемуюfseeko
илиfseeko64
принимающую 64-разрядное смещение.Вот фрагмент из определения в
seekoff
моей системе Linux:LFS выступает за поддержку больших файлов .
Заключение. Хотя стандарт предлагает определение для
streamoff
этого, которое якобы противоречит требованию, котороеseekoff
вызываютfseek
, разработчики библиотек понимают, что они должны вызвать вариант,fseek
который принимает полный диапазон смещений, поддерживаемых ОС.источник
The situation seems to be:
- Ситуация такова , что реализация не допускается не звонитьfseek
вseekoff
. Это должно вызватьfseek
, это не, стандарт говорит, что это должно. Я могу утверждать, что эта реализация недействительна. Я считаю, что это не отвечает на вопрос. Оч, нашел llvm , звонитfseeko
._fseeki64
эту функцию; что также, кажется, нарушает то, что говорит стандарт.fseek
. В другом месте стандарт описывает что-то как «как будто по телефонуfseek(...)
». Если бы он так сильно заботился о буквальном вызовеfseek
, это утверждение было бы другим. Серьезно, что бы вы сделали, если бы реализовывали библиотеку C ++? Вы бы настаивали на вызовеfseek
с младшими 32 битами смещения 64-битного файла, потому что документ говорит вам? Будут ли ваши клиенты благодарить вас за это?