O C ++ usa o streamoff
tipo para representar um deslocamento em um fluxo (arquivo) e é definido da seguinte maneira em [stream.types]:
using streamoff = implementation-defined ;
O tipo streamoff é sinônimo de um dos tipos integrais básicos assinados de tamanho suficiente para representar o tamanho máximo possível de arquivo para o sistema operacional. 287)
287) Normalmente longo.
Isso faz sentido porque permite procurar em arquivos grandes (em vez de usar long
, que podem ter apenas 32 bits de largura).
[filebuf.virtuals] define basic_filebuf
a função de buscar em um arquivo da seguinte maneira:
pos_type seekoff(off_type off, ios_base::seekdir way, ios_base::openmode which = ios_base::in | ios_base::out) override;
off_type
é equivalente a streamoff
, consulte [iostreams.limits.pos]. No entanto, o padrão continua a explicar os efeitos da função. Estou irritado com a última frase, que exige uma chamada para fseek
:
Efeitos : Vamos
width
denotara_codecvt.encoding()
. Seis_open() == false
, ouoff != 0 && width <= 0
, a operação de posicionamento falhará. Caso contrário, seway != basic_ios::cur
ouoff != 0
, e se a última operação foi emitida, atualize a sequência de saída e escreva qualquer sequência de não mudança. Em seguida, procure a nova posição: sewidth > 0
, liguefseek(file, width * off, whence)
, caso contrário, liguefseek(file, 0, whence)
.
fseek
aceita um long
parâmetro Se off_type
e streamoff
for definido como long long
(conforme sugerido pelo padrão), isso poderá levar a uma conversão inativa ao long
chamar fseek(file, width * off, whence)
(levando a erros potencialmente difíceis de diagnosticar). Isso põe em questão toda a lógica para introduzir o streamoff
tipo em primeiro lugar.
Isso é intencional ou um defeito no padrão?
seekoff
necessariamente usarfseek
sob o capô. Em vez disso, o comportamento (presumivelmente familiar?) Defseek
é usado para explicar o queseekoff
está fazendo.fseek
desde que faça algo com o mesmo efeito. Masfseek
com um deslocamento menorLONG_MIN
ou maior queLONG_MAX
não tem efeito, a explicação é, na melhor das hipóteses, incompleta, pelo menos para implementações ondestreamoff
é maior quelong
.Respostas:
Eu acho que a conclusão que você está tirando disso, de que existe uma incompatibilidade entre os fluxos C ++ e
fseek
que levará a erros de tempo de execução, está incorreta. A situação parece ser:Em sistemas onde
long
é de 64 bits,streamoff
é definido comolong
e aseekoff
função chamafseek
.Em sistemas com
long
32 bits, mas o sistema operacional suporta compensações de arquivos de 64 bits,streamoff
é definido comolong long
eseekoff
invoca uma função chamadafseeko
oufseeko64
que aceita um deslocamento de 64 bits.Aqui está um trecho da definição de
seekoff
no meu sistema Linux:LFS significa Suporte a arquivos grandes .
Conclusão: Embora o padrão sugira uma definição
streamoff
que ostensivamente conflite com o requisitoseekoff
invocadofseek
, os designers de bibliotecas entendem que devem chamar a variantefseek
que aceita toda a gama de compensações suportadas pelo sistema operacional.fonte
The situation seems to be:
- A situação é que a implementação não é permitido para não chamarfseek
noseekoff
. Deve chamarfseek
, não é, o padrão diz que precisa. Eu posso argumentar que esta implementação é inválida. Eu acredito que não responde à pergunta. Och, encontrei llvm , ele chamafseeko
._fseeki64
essa função; o que também parece violar o que o padrão diz.fseek
. Em outros lugares, o padrão descreve algo como "como se estivesse ligandofseek(...)
". Se se importasse tanto em ligar literalmentefseek
, essa afirmação seria diferente. Sério, o que você faria se estivesse implementando uma biblioteca C ++? Você insistiria em chamarfseek
com os 32 bits inferiores de um deslocamento de arquivo de 64 bits, porque um documento solicita? Seus clientes agradeceriam por isso?