Search code examples
c++cstdio

Clarification on fsetpos, C++


I am a little confused with function fsetpos in the stdio.h library. I want to be to write to different indexes (i.e do not want to write to a file contiguously) in a file. I was considering using fsetpos however the documentation states..

The internal file position indicator associated with stream is set to the position 
represented by pos, which is a pointer to an fpos_t object whose value shall have been
previously obtained by a call to fgetpos.

It does not make sense to me that I have to set the position based on the call from fgetpos. Whats the point since it will just set it to the position it is already set at. Or I am I not understanding it correctly ?


Solution

  • From the C11 standard, fseek has a similar limitation:

    For a text stream, either offset shall be zero, or offset shall be a value returned by an earlier successful call to the ftell function on a stream associated with the same file and whence shall be SEEK_SET

    The reason is that text streams don't have a one-to-one mapping between the actual bytes of the source and the bytes you would get from fgetc; e.g. on windows systems, the newline character in C tends to be translated into a sequence of two binary characters: carriage return, then line feed.

    Consequently, the notion of arbitrarily positioning a text stream based on a numerical index is fraught with complications and surprises.

    In fact, the documentation of ftell warns

    For a text stream, its file position indicator contains unspecified information, usable by the fseek function for returning the file position indicator for the stream to its position at the time of the ftell call; the difference between two such return values is not necessarily a meaningful measure of the number of characters written or read.

    Binary streams don't have this limitation, although

    A binary stream need not meaningfully support fseek calls with a whence value of SEEK_END


    The above assumes you are working with byte-oriented streams. Wide-oriented streams have additional restrictions. e.g. under Streams:

    Binary wide-oriented streams have the file-positioning restrictions ascribed to both text and binary streams

    and

    For wide-oriented streams, after a successful call to a file-positioning function that leaves the file position indicator prior to the end-of-file, a wide character output function can overwrite a partial multibyte character; any file contents beyond the byte(s) written are henceforth indeterminate

    fsetpos does more than just set the file position: again from the C11 standard:

    The fsetpos function sets the mbstate_t object (if any) and file position indicator

    which makes it more suitable for setting the position in a wide-oriented streams.