C ++ usa el streamoff
tipo para representar un desplazamiento dentro de una secuencia (archivo) y se define de la siguiente manera en [stream.types]:
using streamoff = implementation-defined ;
El tipo streamoff es sinónimo de uno de los tipos integrales básicos firmados de tamaño suficiente para representar el tamaño de archivo máximo posible para el sistema operativo. 287)
287) Típicamente largo largo.
Esto tiene sentido porque permite buscar dentro de archivos grandes (en oposición al uso long
, que puede tener solo 32 bits de ancho).
[filebuf.virtuals] define basic_filebuf
la función de buscar dentro de un archivo de la siguiente manera:
pos_type seekoff(off_type off, ios_base::seekdir way, ios_base::openmode which = ios_base::in | ios_base::out) override;
off_type
es equivalente a streamoff
, vea [iostreams.limits.pos]. Sin embargo, el estándar continúa explicando los efectos de la función. Estoy irritado por la última oración, que requiere una llamada a fseek
:
Efectos : Dejar
width
denotara_codecvt.encoding()
. Siis_open() == false
, ooff != 0 && width <= 0
, entonces la operación de posicionamiento falla. De lo contrario, siway != basic_ios::cur
ooff != 0
, y si se emitió la última operación, actualice la secuencia de salida y escriba cualquier secuencia sin desplazamiento. Luego, busque la nueva posición: siwidth > 0
, llamefseek(file, width * off, whence)
, de lo contrario llamefseek(file, 0, whence)
.
fseek
acepta un long
parámetro Si off_type
y streamoff
se definen como long long
(como lo sugiere el estándar), esto podría conducir a una conversión descendente a la long
hora de llamar fseek(file, width * off, whence)
(lo que podría generar errores potencialmente difíciles de diagnosticar). Esto pone en tela de juicio toda la justificación para introducir el streamoff
tipo en primer lugar.
¿Es esto intencional o un defecto en el estándar?
seekoff
necesariamente se usefseek
debajo del capó. Más bien, el comportamiento (¿presumiblemente familiar?) Defseek
se utiliza para explicar lo queseekoff
está haciendo.fseek
siempre que haga algo con el mismo efecto. Perofseek
con un desplazamiento menorLONG_MIN
o mayor queLONG_MAX
no tiene ningún efecto, por lo que la explicación es, en el mejor de los casos, incompleta, al menos para implementaciones dondestreamoff
es más amplia quelong
.Respuestas:
Creo que la conclusión de que está sacando de esto, que hay una falta de coincidencia entre las transmisiones de C ++ y
fseek
que dará lugar a errores de tiempo de ejecución, es incorrecta. La situación parece ser:En sistemas donde
long
es de 64 bits,streamoff
se define comolong
, y laseekoff
función invocafseek
.En los sistemas donde
long
hay 32 bits pero el sistema operativo admite compensaciones de archivos de 64 bits,streamoff
se define comolong long
eseekoff
invoca una función llamadafseeko
ofseeko64
que acepta un desplazamiento de 64 bits.Aquí hay un fragmento de la definición de
seekoff
en mi sistema Linux:LFS significa Soporte para archivos grandes .
Conclusión: Si bien el estándar sugiere una definición para
streamoff
eso que aparentemente entra en conflicto con el requisito queseekoff
invocafseek
, los diseñadores de bibliotecas entienden que deben llamar a la variantefseek
que acepta la gama completa de compensaciones que admite el sistema operativo.fuente
The situation seems to be:
- La situación es que la aplicación no está permitido no llamarfseek
enseekoff
. Debe llamarfseek
, no lo hace, el estándar dice que tiene que hacerlo. Puedo argumentar que esta implementación no es válida. Creo que no responde la pregunta. Och, encontró llvm , llamafseeko
._fseeki64
esta función; que también parece violar lo que dice el estándar.fseek
. En otra parte, el estándar describe algo como "como si llamarafseek(...)
". Si se preocupara tanto por llamar literalmentefseek
, esa declaración sería diferente. En serio, ¿qué harías si implementaras una biblioteca C ++? ¿Insistiría en llamarfseek
con los 32 bits inferiores de un desplazamiento de archivo de 64 bits, porque un documento se lo indica? ¿Tus clientes te lo agradecerían?