Теперь на примере функций fopen и getc из стандартной библиотеки покажем, как описанные выше части согласуются друг с другом.
Напомним, что файлы в стандартной библиотеке описываются файловыми указателями, а не дескрипторами. Указатель файла - это указатель на структуру, содержащую информацию о файле: указатель на буфер, позволяющий читать файл большими кусками: число незанятых байтов буфера; указатель на следующую позицию в буфере; дескриптор файла; флажки, описывающие режим (чтение/запись), ошибочные состояния и т. д.
Структура данных, описывающая файл, содержится в <stdio.h>, который необходимо включать (с помощью #include) в любой исходный файл, если в том осуществляется стандартный ввод-вывод. Этот же заголовочный файл включен и в исходные тексты библиотеки ввода-вывода.
В следующем фрагменте, типичном для файла <stdio.h>, имена, используемые только в библиотечных функциях, начинаются с подчеркивания. Это сделано для того, чтобы они случайно не совпали с именами, фигурирующими в программе пользователя. Такое соглашение соблюдается во всех программах стандартной библиотеки.
#define NULL 0 #define EOF (-1) #define BUFSIZ 1024 #define OPEN_MAX 20 /* max число одновременно открытых файлов */
typedef struct _iobuf { int cnt; /* количество оставшихся символов */ char *ptr; /* позиция следующего символа */ char *base; /* адрес буфера */ int flag; /* режим доступа */ int fd; /* дескриптор файла */ } FILE;
extern FILE _iob[OPEN_MAX];
#define stdin (&iob[0]) #define stdout (&_iob[1]) #define stderr (&_iob[2])
enum _flags { _READ = 01, /* файл открыт на чтение */ _WRITE = 02, /* файл открыт на запись */ _UNBUF = 04, /* файл не буферизируется */ _EOF = 010, /* в данном файле встретился EOF */ _ERR = 020 /* в данном файле встретилась ошибка */ };
int _fillbuf(FILE *); int _flushbuf(int, FILE *);
#define feof(p) (((p)->flag & _EOF) !- 0) #define ferror(p) (((p)->flag & _ERR) != 0) #define fileno(p) ((p)->fd)
#define getc(p) (--(p)->cnt >= 0 \ ? (unsigned char) *(p)->ptr++ : _fillbuf(p)) #define putc(x,p) (--(p)->cnt >= 0 \ ? *(p)->ptr++ = (x) : _flushbuf((x),p))