Выполнение всех функций чтения и записи приводит к последовательному изменению текущей позиции ввода-вывода в потоке. Например, после вызова функции fgetc указатель позиции чтения в структуре управления потоком устанавливается за прочитанным символом. Аналогично, после обращения к функции fputc указатель позиции записи в структуре управления потоком будет установлен после записанного символа. Чтобы обеспечить установку произвольной позиции ввода-вывода в файловом потоке, следует применять функцию fseek. Спецификация формата ее вызова имеет вид:
int fseek(FILE* stream, long offset, int whence);
Аргумент stream специфицирует файловый поток, где нужно позиционировать операции ввода или вывода. Аргумент offset задает смещение в байтах новой позиции ввода-вывода в файле, с которым связан поток. В зависимости от значения аргумента whence смещение исчисляется от начала файла, текущей позиции или от конца файла. Чтобы декларировать нужный способ смещения, используются макросы SEEK_SET, SEEK_CUR и SEEK_END, которые обычно определены в заголовочном файле stdio.h значениями 0, 1 и 2, соответственно.
Спецификация аргумента whence значением SEEK_END обычно имеет смысл в сочетании с отрицательной величиной параметра смещения offset. В этом случае сдвиг текущей позиции ввода-вывода исчисляется в направлении от конца файла к его началу. Если аргумент offset задает нулевое смещение (0L), а значение аргумента whence равно SEEK_END, позиция ввода или вывода устанавливается в конец файла. Последующее обращение к функция записи данных в поток эквивалентно добавлению новой информацию в конец файла.
Функция fseek допускает установку позиции вывода за концом файла. Это не приводит к увеличению размера файла до записи данных с установленной позиции вывода. Полученный промежуток будет читаться как нулевые байты, пока в него не будет что-либо записано.
Спецификация аргумента whence значением SEEK_SET обычно имеет смысл в сочетании с положительной величиной параметра смещения offset. В этом случае сдвиг текущей позиции ввода-вывода исчисляется в направлении от начала файла к его концу. Если аргумент offset задает нулевое смещение (0L), а значение аргумента whence равно SEEK_SET, позиция ввода-вывода устанавливается в начало файла.
Установка позиции ввода-вывода перед началом файла считается ошибкой позиционирования. В этом случае функция fseek возвращает отрицательное значение. При успехе позиционирования функция fseek возвращает нулевой код.
Чтобы избежать ошибок позиционирования указателя файлового потока в начало файла, рекомендуется использовать функцию rewind. Спецификация формата ее вызова имеет вид:
void rewind(FILE* stream);
Аргумент stream обозначает файловый поток, где нужно установить позицию ввода-вывода в начало файла. Функцию rewind можно рассматривать как частный вариант функции fseek, свободный от ошибок позиционирования в потоке ввода-вывода. Поэтому функция rewind не имеет кода возврата в отличие от универсальной функции позиционирования fseek.
Для эффективной буферизованной обработки больших файлов целесообразно выполнять смещение с помощью функции fseek относительно текущей позиции ввода-вывода, задавая аргумент whence значением константы SEEK_CUR. Когда аргумент whence функции fseek специфицирован значением SEEK_CUR, смещение, заданное параметром offset, исчисляется от текущей позиции в файле. Отрицательное значение параметра offset устанавливает смещение позиции ввода-вывода к началу файла, положительное концу файла.
Для сдвига относительно текущей позиции файла желательно иметь возможность ее определить. Такую возможность предоставляет функция ftell. Спецификация формата ее вызова имеет вид:
long ftell(FILE* stream);
Функция ftell возвращает смещение в байтах текущей позиции ввода-вывода относительно начала файла в потоке, который специфицирован аргументом stream. В случае ошибки измерения возвращается отрицательный код (-1L).
Использование функций fseek и ftell поясняет исходный код прикладной функции fsize, которая определяет текущий размер файла, открытого для потоковой обработки данных.
/* Определение размера файла */
long fsize(FILE* stream) {
long offset;    /* текущее смещение указателя потока */
long size;      /* размер файла */
/* Запомнить текущее смещение указателя потока */
offset = ftell(stream);
/* Установить указатель в конец потока */
fseek(stream, 0L, SEEK_END);
/* Определить размер файла по конечной позиции потока */
size = ftell(stream);
/* Восстановить исходное смещение указателя потока */
fseek(stream, offset, SEEK_SET);
/* Возврат величины размера файла */
return(size);
} /* fsize */
Принцип измерения длины файла, реализованный в функции fsize, основан на установке текущей позиции указателя потока в конец файла с помощью функции fseek. Тогда текущее смещение указателя, измеренное функцией ftell, будет равно искомой длине файла в байтах.