`
Читать книги » Книги » Компьютеры и Интернет » Интернет » Linux программирование в примерах - Роббинс Арнольд

Linux программирование в примерах - Роббинс Арнольд

1 ... 39 40 41 42 43 ... 253 ВПЕРЕД
Перейти на страницу:

int whence

Описывает положение в файле, относительно которого отсчитывается offset. См. табл. 4.4.

Таблица 4.4. Значения whence для lseek()

Именованная константа Значение Комментарий SEEK_SET 0 offset абсолютно, т.е. относительно начала файла SEEK_CUR 1 offset относительно текущей позиции в файле SEEK_END 2 offset относительно конца файла.

Большое количество старого кода использует числовые значения, приведенные в табл. 4.4. Однако, любой новый код, который вы пишете, должен использовать символические имена, значение которых более ясно.

Смысл значений и их действие на положение в файле показаны на рис. 4.1. При условии, что файл содержит 3000 байтов и что перед каждым вызовом lseek() текущим является смещение 2000 байтов, новое положение после каждого вызова будет следующим.

Рис. 4.1. Смещения для lseek()

Отрицательные смещения относительно начала файла бессмысленны; они вызывают ошибку «недействительный параметр».

Возвращаемое значение является новым положением в файле. Поэтому, чтобы получить ваше текущее местоположение в файле, используйте

off_t curpos;

...

curpos = lseek(fd, (off_t)0, SEEK_CUR);

Буква l в lseek() означает long. lseek() был введен в V7 Unix, когда размеры файлов были увеличены; в V6 был простой системный вызов seek(). В результате большое количество старой документации (и кода) рассматривает параметр offset как имеющий тип long, и вместо приведения к типу off_t довольно часто можно видеть суффикс L в константных значениях смешений:

curpos = lseek(fd, 0L, SEEK_CUR);

На системах с компилятором стандартного С, где lseek() объявлена с прототипом, такой старый код продолжает работать, поскольку компилятор автоматически преобразует 0L из long в off_t, если это различные типы.

Одной интересной и важной особенностью lseek() является то, что она способна устанавливать смещение за концом файла. Любые данные, которые впоследствии записываются в это место, попадают в файл, но с образованием «интервала» или «дыры» между концом предыдущих данных файла и началом новых данных. Данные в промежутке читаются, как если бы они содержали все нули.

Следующая программа демонстрирует создание дыр. Она записывает три экземпляра struct в начало, середину и дальний конец файла. Выбранные смешения (строки 16–18, третий элемент каждой структуры) произвольны, но достаточно большие для демонстрации особенности:

1  /* ch04-holes.c --- Демонстрация lseek() и дыр в файлах. */

2

3  #include <stdio.h> /* для fprintf(), stderr, BUFSIZ */

4  #include <errno.h> /* объявление errno */

5  #include <fcntl.h> /* для flags для open() */

6  #include <string.h> /* объявление strerror() */

7  #include <unistd.h> /* для ssize_t */

8  #include <sys/types.h> /* для off_t, etc. */

9  #include <sys/stat.h>  /* для mode_t */

10

11 struct person {

12  char name[10]; /* имя */

13  char id[10]; /* идентификатор */

14  off_t pos; /* положение в файле для демонстрации */

15 } people[] = {

16  { "arnold", "123456789", 0 },

17  { "miriam", "987654321", 10240 },

18  { "joe", "192837465", 81920 },

19 };

20

21 int

22 main(int argc, char **argv)

23 {

24  int fd;

25  int i, j;

26

27  if (argc < 2) {

28   fprintf(stderr, "usage: %s filen", argv[0]);

29   return 1;

30  }

31

32  fd = open(argv[1], O_RDWR | O_CREAT | O_TRUNC, 0666);

33  if (fd < 0) {

34   fprintf(stderr, "%s: %s: cannot open for read/write: %sn",

35    argv[0], argv[1], strerror(errno));

36   return 1;

37  }

38

39  j = sizeof(people) / sizeof(people[0]); /* число элементов */

Строки 27–30 гарантируют, что программа была вызвана правильно. Строки 32–37 открывают именованный файл и проверяют успешность открытия.

Вычисление числа элементов j массива в строке 39 использует отличный переносимый трюк число элементов является размером всего массива, поделенного на размер первого элемента. Красота этого способа в том, что он всегда верен: неважно, сколько элементов вы добавляете в массив или удаляете из него, компилятор это выяснит. Он не требует также завершающей сигнальной метки; т.е. элемента, в котором все поля содержат нули, NULL или т.п.

1 ... 39 40 41 42 43 ... 253 ВПЕРЕД
Перейти на страницу:

Откройте для себя мир чтения на siteknig.com - месте, где каждая книга оживает прямо в браузере. Здесь вас уже ждёт произведение Linux программирование в примерах - Роббинс Арнольд, относящееся к жанру Интернет. Никаких регистраций, никаких преград - только вы и история, доступная в полном формате. Наш литературный портал создан для тех, кто любит комфорт: хотите читать с телефона - пожалуйста; предпочитаете ноутбук - идеально! Все книги открываются моментально и представлены полностью, без сокращений и скрытых страниц. Каталог жанров поможет вам быстро найти что-то по настроению: увлекательный роман, динамичное фэнтези, глубокую классику или лёгкое чтение перед сном. Мы ежедневно расширяем библиотеку, добавляя новые произведения, чтобы вам всегда было что открыть "на потом". Сегодня на siteknig.com доступно более 200000 книг - и каждая готова стать вашей новой любимой. Просто выбирайте, открывайте и наслаждайтесь чтением там, где вам удобно.

Комментарии (0)