Что такое функция fseek в C/C++?

«Что такое функция fseek в C/C++?» — вопрос из категории C++ Core, который задают на 25% собеседований C/C++ Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

fseek — это функция стандартной библиотеки C (объявленная в <cstdio>), которая изменяет позицию указателя файлового потока (FILE*) для последующих операций чтения или записи. В C++ её использование оправдано при работе с унаследованным C-кодом или для низкоуровневых операций с файлами.

Сигнатура:

int fseek(FILE *stream, long int offset, int origin);

Параметры:

  1. stream — указатель на файловый поток.
  2. offset — смещение в байтах. Может быть отрицательным для перемещения назад.
  3. origin — точка отсчёта для смещения. Может принимать одно из трёх значений:
    • SEEK_SET — начало файла.
    • SEEK_CUR — текущая позиция указателя в файле.
    • SEEK_END — конец файла.

Возвращаемое значение: 0 в случае успеха, ненулевое значение (обычно -1) в случае ошибки.

Пример: чтение данных из середины файла

#include <cstdio>
#include <iostream>

int main() {
    FILE* pFile = std::fopen("data.bin", "rb");
    if (!pFile) {
        std::perror("Ошибка открытия файла");
        return 1;
    }

    // Перемещаем указатель на 100 байт от начала файла
    if (std::fseek(pFile, 100, SEEK_SET) != 0) {
        std::perror("Ошибка fseek");
        std::fclose(pFile);
        return 1;
    }

    char buffer[50];
    std::size_t bytesRead = std::fread(buffer, 1, sizeof(buffer), pFile);
    std::cout << "Прочитано " << bytesRead << " байт.n";

    std::fclose(pFile);
    return 0;
}

Важные замечания и ограничения:

  • Размер файла: Тип long int для смещения может быть недостаточным для файлов размером >2 ГБ. В POSIX-системах используйте fseeko с off_t, в Windows — _fseeki64 с __int64.
  • Потоки без произвольного доступа: fseek не работает с потоками, которые не поддерживают произвольный доступ (например, pipes, терминалы, сетевые сокеты).
  • Буферизация: При переключении между чтением и записью после fseek может потребоваться вызов fflush или функции позиционирования.
  • В C++: Для типобезопасного и объектно-ориентированного подхода предпочтительнее использовать потоки (std::fstream) и методы seekg/seekp.