WWW.DISS.SELUK.RU

БЕСПЛАТНАЯ ЭЛЕКТРОННАЯ БИБЛИОТЕКА
(Авторефераты, диссертации, методички, учебные программы, монографии)

 

Pages:     | 1 ||

«ЯЗЫК С Аннотация Язык C(произносится си) — это универсальный язык программирования, для которого характерны экономичность выражения, современный поток управления и структуры данных, богатый набор операторов. Язык C не ...»

-- [ Страница 2 ] --

Объединив все эти факты, мы написали простую программу для копирования ввода на вывод, эквивалентную программе копировки файлов, написанной в главе 1.

На системе UNIX эта программа будет копировать что угодно куда угодно, потому что ввод и вывод могут быть перенаправлены на любой файл или устройство.

#DEFINE BUFSIZE 512 /*BEST SIZE FOR PDP-11 UNIX*/ MAIN() /*COPY INPUT TO OUTPUT*/ CHAR BUF[BUFSIZE];

WHILE((N=READ(0,BUF,BUFSIZE))>0) WRITE(1,BUF,N);

Если размер файла не будет кратен BUFSIZE, то при некотором обращении к READ будет возвращено меньшее число байтов, которые затем записываются с помощью WRITE; при следующем после этого обращении к READ будет возвращен нуль.

Поучительно разобраться, как можно использовать функции READ и WRITE для построения процедур более высокого уровня, таких как GETCHAR, PUTCHAR и т.д.

Вот, например, вариант функции GETCHAR, осуществляющий ввод без использования буфера.

#DEFINE CMASK 0377 /*FOR MAKING CHAR'S > 0*/

GETCHAR() /*UNBUFFERED SINGLE CHARACTER INPUT*/

RETURN((READ(0,&C,1)>0 7 & CMASK : EOF);

Переменная "C" должна быть описана как CHAR, потому что функция READ принимает указатель на символы. Возвращаемый символ должен быть маскирован числом 0377 для гарантии его положительности; в противном случае знаковый разряд может сделать его значение отрицательным. (Константа 0377 подходит для эвм PDPно не обязательно для других машин).

Второй вариант функции GETCHAR осуществляет ввод большими порциями, а выдает символы по одному за обращение.

#DEFINE CMASK 0377 /*FOR MAKING CHAR'S>0*/ #DEFINE BUFSIZE GETCHAR() /*BUFFERED VERSION*/ STATIC CHAR BUF[BUFSIZE];

STATIC CHAR *BUFP = BUF;

STATIC INT N = 0;

IF (N==0) \( /*BUFFER IS EMPTY*/ N=READ(0,BUF,BUFSIZE);

BUFP = BUF;

RETURN((--N>=0)? *BUFP++ & CMASK : EOF);

8.3. Открытие, создание, закрытие и расцепление (UNLINK) Кроме случая, когда по умолчанию определены стандартные файлы ввода, вывода и ошибок, вы должны явно открывать файлы, чтобы затем читать из них или писать в них. Для этой цели существуют две точки входа: OPEN и CREAT.

Функция OPEN весьма сходна с функцией FOPEN, рассмотренной в главе 7, за исключением того, что вместо возвращения указателя файла она возвращает дескриптор файла, который является просто целым типа INT.

INT FD;

FD=OPEN(NAME,RWMODE);

Как и в случае FOPEN, аргумент NAME является символьной строкой, соответствующей внешнему имени файла. Однако аргумент, определяющий режим доступа, отличен: RWMODE равно: 0 — для чтения, 1 — для записи, 2 — для чтения и записи. Если происходит какая-то ошибка, функция OPEN возвращает "-1"; в противном случае она возвращает действительный дескриптор файла.

Попытка открыть файл, который не существует, является ошибкой. Точка входа CREAT предоставляет возможность создания новых файлов или перезаписи старых. В результате обращения FD=CREAT(NAME,PMODE);

возвращает дескриптор файла, если оказалось возможным создать файл с именем NAME, и "-1" в противном случае. Если файл с таким именем уже существует, CREAT усечет его до нулевой длины; создание файла, который уже существует, не является ошибкой.

Если файл является совершенно новым, то CREAT создает его с определенным режимом защиты, специфицируемым аргументом PMODE. В системе файлов на UNIX с файлом связываются девять битов защиты информации, которые управляют разрешением на чтение, запись и выполнение для владельца файла, для группы владельцев и для всех остальных пользователей. Таким образом, трехзначное восьмеричное число наиболее удобно для спецификации разрешений. Например, число 0755 свидетельствует о разрешении на чтение, запись и выполнение для владельца и о разрешении на чтение и выполнение для группы и всех остальных.

Для иллюстрации ниже приводится программа копирования одного файла в другой, являющаяся упрощенным вариантом утилиты CP системы UNIX. (Основное упрощение заключается в том, что наш вариант копирует только один файл и что второй аргумент не должен быть справочником).

#DEFINE NULL #DEFINE BUFSIZE #DEFINE PMODE 0644/*RW FOR OWNER,R FOR GROUP,OTHERS*/ MAIN(ARGC,ARGV) /*CP: COPY F1 TO F2*/ INT ARGC;

CHAR *ARGV[];

INT F1, F2, N;

CHAR BUF[BUFSIZE];

ERROR("USAGE:CP FROM TO", NULL);

IF ((F1=OPEN(ARGV[1],0))== -1) ERROR("CP:CAN'T OPEN % S", ARGV[1]);

IF ((F2=CREAT(ARGV[2],PMODE))== -1) ERROR("CP: CAN'T CREATE % S", ARGV[2]);

WHILE ((N=READ(F1,BUF,BUFSIZE))>0) IF (WRITE(F2,BUF,N) !=N) ERROR("CP: WRITE ERROR", NULL);

EXIT(0);

ERROR(S1,S2) /*PRINT ERROR MESSAGE AND DIE*/ CHAR *S1, S2;

PRINTF(S1,S2);

PRINTF("\N");

EXIT(1);

Существует ограничение (обычно 15 — 25) на количество файлов, которые программа может иметь открытыми одновременно. В соответствии с этим любая программа, собирающаяся работать со многими файлами, должна быть подготовлена к повторному использованию дескрипторов файлов. Процедура CLOSE прерывает связь между дескриптором файла и открытым файлом и освобождает дескриптор файла для использования с некоторым другим файлом. Завершение выполнения программы через EXIT или в результате возврата из ведущей программы приводит к закрытию всех открытых файлов.

Функция расцепления UNLINK (FILENAME) удаляет из системы файлов файл с именем FILENAME ( из данного справочного файла. Файл может быть сцеплен с другим справочником, возможно, под другим именем — примеч.переводчика).



Упражнение 8-1.

Перепишите программу CAT из главы 7, используя функции READ, WRITE, OPEN и CLOSE вместо их эквивалентов из стандартной библиотеки. Проведите эксперименты для определения относительной скорости работы этих двух вариантов.

8.4. Произвольный доступ — SEEK и LSEEK Нормально при работе с файлами ввод и вывод осуществляется последовательно:

при каждом обращении к функциям READ и WRITE чтение или запись начинаются с позиции, непосредственно следующей за предыдущей обработанной. Но при необходимости файл может читаться или записываться в любом произвольном порядке. Обращение к системе с помощью функции LSEEK позволяет передвигаться по файлу, не производя фактического чтения или записи. В результате обращения LSEEK(FD,OFFSET,ORIGIN);

текущая позиция в файле с дескриптором FD передвигается на позицию OFFSET (смещение), которая отсчитывается от места, указываемого аргументом ORIGIN (начало отсчета). Последующее чтение или запись будут теперь начинаться с этой позиции.

Аргумент OFFSET имеет тип LONG; FD и ORIGIN имеют тип INT.

Аргумент ORIGIN может принимать значения 0,1 или 2, указывая на то, что величина OFFSET должна отсчитываться соответственно от начала файла, от текущей позиции или от конца файла. Например, чтобы дополнить файл, следует перед записью найти его конец:

LSEEK(FD,0L,2);

чтобы вернуться к началу ("перемотать обратно"), можно написать:

LSEEK(FD,0L,0);

обратите внимание на аргумент 0L; его можно было бы записать и в виде (LONG) 0.

Функция LSEEK позволяет обращаться с файлами примерно так же, как с большими массивами, правда ценой более медленного доступа. следующая простая функция, например, считывает любое количество байтов, начиная с произвольного места в файле.

GET(FD,POS,BUF,N) /*READ N BYTES FROM POSITION POS*/ LONG POS;

CHAR *BUF;

LSEEK(FD,POS,0); /*GET TO POS*/ RETURN(READ(FD,BUF,N));

В более ранних редакциях, чем редакция 7 системы UNIX, основная точка входа в систему ввода-вывода называется SEEK. Функция SEEK идентична функции LSEEK, за исключением того, что аргумент OFFSET имеет тип INT, а не LONG. в соответствии с этим, поскольку на PDP-11 целые имеют только 16 битов, аргумент OFFSET, указываемый функции SEEK, ограничен величиной 65535; по этой причине аргумент ORIGIN может иметь значения 3, 4, 5, которые заставляют функцию SEEK умножить заданное значение OFFSET на 512 (количество байтов в одном физическом блоке) и затем интерпретировать ORIGIN, как если это 0, 1 или 2 соответственно.

Следовательно, чтобы достичь произвольного места в большом файле, нужно два обращения к SEEK: сначала одно, которое выделяет нужный блок, а затем второе, где ORIGIN имеет значение 1 и которое осуществляет передвижение на желаемый байт внутри блока.

Упражнение 8-2.

Очевидно, что SEEK может быть написана в терминалах LSEEK и наоборот.

напишите каждую функцию через другую.

8.5. Пример — реализация функций FOPEN и GETC Давайте теперь на примере реализации функций FOPEN и GETC из стандартной библиотеки подпрограмм продемонстрируем, как некоторые из описанных элементов объединяются вместе.

Напомним, что в стандартной библиотеке файлы описыватся посредством указателей файлов, а не дескрипторов. Указатель файла является указателем на структуру, которая содержит несколько элементов информации о файле: указатель буфера, чтобы файл мог читаться большими порциями; счетчик числа символов, оставшихся в буфере; указатель следующей позиции символа в буфере; некоторые признаки, указывающие режим чтения или записи и т.д.; дескриптор файла.

Описывающая файл структура данных содержится в файле STDIO.H, который должен включаться (посредством #INCLUDE) в любой исходный файл, в котором используются функции из стандартной библиотеки. Он также включается функциями этой библиотеки. В приводимой ниже выдержке из файла STDIO.H имена, предназначаемые только для использования функциями библиотеки, начинаются с подчеркивания, с тем чтобы уменьшить вероятность совпадения с именами в программе пользователя.

DEFINE _BUFSIZE DEFINE _NFILE 20 /*FILES THAT CAN BE HANDLED*/ TYPEDEF STRUCT _IOBUF \( CHAR *_PTR; /*NEXT CHARACTER POSITION*/ CHAR *_BASE; /*LOCATION OF BUFFER*/ ) FILE;

XTERN FILE _IOB[_NFILE];

DEFINE _READ 01 /* FILE OPEN FOR READING */ DEFINE _WRITE 02 /* FILE OPEN FOR WRITING */ DEFINE _UNBUF 04 /* FILE IS UNBUFFERED */ DEFINE _BIGBUF 010 /* BIG BUFFER ALLOCATED */ DEFINE _EOF 020 /* EOF HAS OCCURRED ON THIS FILE */ DEFINE _ERR

/* ERROR HAS OCCURRED ON THIS FILE */

DEFINE NULL DEFINE EOF (-1) DEFINE GETC(P) (--(P)->_CNT >= 0 \ ? *(P)->_PTR++ & 0377 : _FILEBUF(P)) DEFINE GETCHAR() GETC(STDIN) DEFINE PUTC(X,P) (--(P)->_CNT >= 0 \ ? *(P)->_PTR++ = (X) : _FLUSHBUF((X),P)) В нормальном состоянии макрос GETC просто уменьшает счетчик, передвигает указатель и возвращает символ. (Если определение #DEFINE слишком длинное, то оно продолжается с помощью обратной косой черты). Если однако счетчик становится отрицательным, то GETC вызывает функцию _FILEBUF, которая снова заполняет буфер, реинициализирует содержимое структуры и возвращает символ. Функция может предоставлять переносимый интерфейс и в то же время содержать непереносимые конструкции: GETC маскирует символ числом 0377, которое подавляет знаковое расширение, осуществляемое на PDP-11, и тем самым гарантирует положительность всех символов.

Хотя мы не собираемся обсуждать какие-либо детали, мы все же включили сюда определение макроса PUTC, для того чтобы показать, что она работает в основном точно также, как и GETC, обращаясь при заполнении буфера к функции _FLUSHBUF.

Теперь может быть написана функция FOPEN. Большая часть программы функции FOPEN связана с открыванием файла и расположением его в нужном месте, а также с установлением битов признаков таким образом, чтобы они указывали нужное состояние. Функция FOPEN не выделяет какой-либо буферной памяти; это делается функцией _FILEBUF при первом чтении из файла.

#INCLUDE #DEFINE PMODE 0644 /*R/W FOR OWNER;R FOR OTHERS*/ FILE *FOPEN(NAME,MODE) /*OPEN FILE,RETURN FILE PTR*/ REGISTER CHAR *NAME, *MODE;

REGISTER INT FD;

IF(*MODE !='R'&&*MODE !='W'&&*MODE !='A') \( FPRINTF(STDERR,"ILLEGAL MODE % S OPENING % S\N", MODE,NAME);

FOR (FP=_IOB;FP_FLAG & (_READ \! _WRITE))==0) BREAK; /*FOUND FREE SLOT*/ IF(FP>=_IOB+_NFILE) /*NO FREE SLOTS*/ IF(*MODE=='W') /*ACCESS FILE*/ FD=CREAT(NAME,PMODE);

ELSE IF(*MODE=='A') \( IF((FD=OPEN(NAME,1))==-1) FD=CREAT(NAME,PMODE);

\) ELSE IF(FD==-1) /*COULDN'T ACCESS NAME*/ FP->_FD=FD;

FP->_CNT=0;

FP->_BASE=NULL;

FP->_FLAG &=(_READ \! _WRITE);

FP->_FLAG \!=(*MODE=='R')? _READ : _WRITE;

RETURN(FP);

Функция _FILEBUF несколько более сложная. Основная трудность заключается в том, что _FILEBUF стремится разрешить доступ к файлу и в том случае, когда может не оказаться достаточно места в памяти для буферизации ввода или вывода. если пространство для нового буфера может быть получено обращением к функции CALLOC, то все отлично; если же нет, то _FILEBUF осуществляет небуферизованный ввод/ вывод, используя отдельный символ, помещенный в локальном массиве.

#INCLUDE _FILLBUF(FP) /*ALLOCATE AND FILL INPUT BUFFER*/ REGISTER FILE *FP;

STATIC CHAR SMALLBUF(NFILE);/*FOR UNBUFFERED 1/0*/ CHAR *CALLOC(); IF((FR->_FLAG&_READ)==0\!\!(FP->_FLAG&(EOF\!_ERR))\!= WHILE(FP->_BASE==NULL) /*FIND BUFFER SPACE*/ IF(FP->_FLAG & _UNBUF) /*UNBUFFERED*/ FP->_BASE=&SMALLBUF[FP->_FD];

ELSE IF((FP->_BASE=CALLOC(_BUFSIZE,1))==NULL) FP->_FLAG \!=_UNBUF; /*CAN'T GET BIG BUF*/ FP->_FLAG \!=_BIGBUF; /*GOT BIG ONE*/ FP->_PTR=FPBASE; FP->_CNT=READ(FP->_FD, FP->_PTR, FP->_FLAG & _UNBUF? 1 : _BUFSIZE); FF(--FP->_CNT_CNT== -1) RETURN(*FP->_PTR++ & 0377); /*MAKE CHAR POSITIVE*/ ) При первом обращении к GETC для конкретного файла счетчик оказывается равным нулю, что приводит к обращению к _FILEBUF. Если функция _FILEBUF найдет, что этот файл не открыт для чтения, она немедленно возвращает EOF. В противном случае она пытается выделить большой буфер, а если ей это не удается, то буфер из одного символа. При этом она заносит в _FLAG соответствующую информацию о буферизации.

Раз буфер уже создан, функция _FILEBUF просто вызывает функцию READ для его заполнения, устанавливает счетчик и указатели и возвращает символ из начала Единственный оставшийся невыясненным вопрос состоит в том, как все начинается. Массив _IOB должен быть определен и инициализирован для STDIN, STDOUT и STDERR:

FILE _IOB[NFILE] = \( (NULL,0,_READ,0), /*STDIN*/ (NULL,0,NULL,1), /*STDOUT*/ (NULL,0,NULL,_WRITE \! _UNBUF,2) /*STDERR*/ Из инициализации части _FLAG этого массива структур видно, что файл STDIN предназначен для чтения, файл STDOUT — для записи и файл STDERR — для записи без использования буфера.

Перепишите функции FOPEN и _FILEBUF, используя поля вместо явных побитовых операций.

Разработайте и напишите функции _FLUSHBUF и FCLOSE.

Стандартная библиотека содержит функцию FSEEK(FP, OFFSET, ORIGIN) которая идентична функции LSEEK, исключая то, что FP является указателем файла, а не дескриптором файла. Напишите FSEEK. Убедитесь, что ваша FSEEK правильно согласуется с буферизацией, сделанной для других функций библиотеки.

8.6. Пример — распечатка справочников Иногда требуется другой вид взаимодействия с системой файлов — определение информации о файле, а не того, что в нем содержится. Примером может служить команда LS ("список справочника") системы UNIX. По этой команде распечатываются имена файлов из справочника и, необязательно, другая информация, такая как размеры, разрешения и т.д.

Поскольку, по крайней мере, на системе UNIX справочник является просто файлом, то в такой команде, как LS нет ничего особенного; она читает файл и выделяет нужные части из находящейся там информации. Однако формат информации определяется системой, так что LS должна знать, в каком виде все представляется в системе.

Мы это частично проиллюстрируем при написании программы FSIZE.

Программа FSIZE представляет собой специальную форму LS, которая печатает размеры всех файлов, указанных в списке ее аргументов. Если один из файлов является справочником, то для обработки этого справочника программа FSIZE обращается сама к себе рекурсивно. если же аргументы вообще отсутствуют, то обрабатывается текущий справочник.

Для начала дадим краткий обзор структуры системы файлов. Справочник — это файл, который содержит список имен файлов и некоторое указание о том, где они размещаются. Фактически это указание является индексом для другой таблицы, которую называют "I — узловой таблицей". Для файла I-узел — это то, где содержится вся информация о файле, за исключением его имени. Запись в справочнике состоит только из двух элементов: номера I-узла и имени файла. Точная спецификация поступает при включении файла SYS/DIR.H, который содержит #DEFINE DIRSIZ 14 /*MAX LENGTH OF FILE NAME*/

STRUCT DIRECT /*STRUCTURE OF DIRECTORY ENTRY*/

INO_T&_INO; /*INODE NUMBER*/ CHAR &_NAME[DIRSIZ]; /*FILE NAME*/ "Тип" INO_T — это определяемый посредством TYPEDEF тип, который описывает индекс I-узловой таблицы. На PDP-11 UNIX этим типом оказывается UNSIGNED, но это не тот сорт информации, который помещают внутрь программы: на разных системах этот тип может быть различным. Поэтому и следует использовать TYPEDEF.

Полный набор "системных" типов находится в файле SYS/TUPES.H.

Функция STAT берет имя файла и возвращает всю содержащуюся в I-ом узле информацию об этом файле (или -1, если имеется ошибка). Таким образом, в результате

STRUCT STAT STBUF;

CHAR *NAME;

STAT(NAME,&STBUF);

структура STBUF наполняется информацией из I-го узла о файле с именем NAME. Структура, описывающая возвращаемую функцией STAT информацию, находится в файле SYS/STAT.H и выглядит следующим образом:

STRUCT STAT /*STRUCTURE RETURNED BY STAT*/

TIME_T ST_ATIME; /* TIME LAST ACCESSED */ TIME_T ST_MTIME; /* TIME LAST MODIFIED */ TIME_T ST_CTIME; /* TIME ORIGINALLY CREATED */ Большая часть этой информации объясняется в комментариях. Элемент ST.MODE содержит набор флагов, описывающих файл; для удобства определения флагов также находятся в файле SYS/STAT.H.

#DEFINE S_IFDIR 0040000 /* DIRECTORY */ #DEFINE S_IFCHR 0020000 /* CHARACTER SPECIAL */ #DEFINE S_IFBLK 0060000 /* BLOCK SPECIAL */ #DEFINE S_IFREG 0100000 /* REGULAR */ #DEFINE S_ISUID 04000 /* SET USER ID ON EXECUTION */ #DEFINE S_ISGID 02000 /* SET GROUP ID ON EXECUTION */ #DEFINE S_ISVTX 01000 /*SAVE SWAPPED TEXT AFTER USE*/ #DEFINE S_IREAD 0400 /* READ PERMISSION */ Теперь мы в состоянии написать программу FSIZE. Если полученный от функции STAT режим указывает, что файл не является справочником, то его размер уже под рукой и может быть напечатан непосредственно. Если же он оказывается справочником, то мы должны обрабатывать этот справочник отдельно для каждого файла; так как справочник может в свою очередь содержать подсправочники, этот процесс обработки является рекурсивным.

Как обычно, ведущая программа главным образом имеет дело с командной строкой аргументов; она передает каждый аргумент функции FSIZE в большой буфер.

#INCLUDE #INCLUDE /*TYPEDEFS*/ #INCLUDE /*DIRECTORY ENTRY STRUCTURE*/ #INCLUDE /*STRUCTURE RETURNED BY STAT*/ #DEFINE BUFSIZE MAIN(ARGC,ARGV) /*FSIZE:PRINT FILE SIZES*/ CHAR *ARGV[];

CHAR BUF[BUFSIZE];

IF(ARGC==1) \( /*DEFAULT:CURRENT DIRECTORY*/ ATRCPY(BUF,".");

FSIZE(BUF);

WHILE(--ARGC>0) \( STRCPY(BUF,*++ARGV);

Функция FSIZE печатает размер файла. Если однако файл оказывается справочником, то FSIZE сначала вызывает функцию DIRECTORY для обработки всех указанных в нем файлов. Обратите внимание на использование имен флагов S_IFMT и _IFDIR из файла STAT.H.

FSIZE(NAME) /*PRINT SIZE FOR NAME*/ CHAR *NAME;

STRUCT STAT STBUF;

IF(STAT(NAME,&STBUF)== -1) \( FPRINTF(STDERR,"FSIZE:CAN'T FIND %S\N",NAME); RETURN;

IF((STBUF.ST_MODE & S_IFMT)==S_IFDIR) PRINTF("% 8LD % S\N",STBUF.ST_SIZE,NAME);

Функция DIRECTORY является самой сложной. Однако значительная ее часть связана с созданием для обрабатываемого в данный момент файла его полного имени, по которому можно восстановить путь в дереве.

DIRECTORY(NAME) /*FSIZE FOR ALL FILES IN NAME*/ CHAR *NAME;

STRUCT DIRECT DIRBUF;

NBP=NAME+STRLEN(NAME);

*NBP++='/'; /*ADD SLASH TO DIRECTORY NAME*/ IF(NBP+DIRSIZ+2>=NAME+BUFSIZE) /*NAME TOO LONG*/ IF((FD=OPEN(NAME,0))== -1) WHILE(READ(FD,(CHAR *)&DIRBUF,SIZEOF(DIRBUF))>0) \( IF(DIRBUF.D_INO==0) /*SLOT NOT IN USE*/ CONTINUE;

IF(STRCMP (DIRBUF.D_NAME,".")== \!\! STRCMP(DIRBUF.D_NAME,"..")== CONTINUE; /*SKIP SELF AND PARENT*/ FOR (I=0,NEP=NBP;IS.PTR; ; G=P, P=P->S.PTR) \( IF (P->S.SIZE>=NUNITS) \( /*BIG ENOUGH*/ IF (P->S.SIZE==NUNITS) /*EXACTLY*/ G->S.PTR=P->S.PTR;

ELSE \( /*ALLOCATE TAIL END*/ P->S.SIZE-=NUNITS;

P+=P->S.SIZE;

P->S.SIZE=NUNITS;

RETURN((CHAR *)(P+1));

IF(P==ALLOCP) /*WRAPPED AROUND FREE LIST*/ IF((P=MORECORE(NUNITS))==NULL) RETURN(NULL); /*NONE LEFT*/ Переменная BASE используется для начала работы. Если ALLOCP имеет значение NULL, как в случае первого обращения к ALLOC, то создается вырожденный свободный список: он состоит из свободного блока размера нуль и указателя на самого себя. В любом случае затем исследуется свободный список. Поиск свободного блока подходящего размера начинается с того места (ALLOCP), где был найден последний блок; такая стратегия помогает сохранить однородность диска. Если найден слишком большой блок, то пользователю предлагается его хвостовая часть; это приводит к тому, что в заголовке исходного блока нужно изменить только его размер.

Во всех случаях возвращаемый пользователю указатель указывает на действительно свободную область, лежащую на единицу дальше заголовка. Обратите внимание на то, что функция ALLOC перед возвращением "P" преобразует его в указатель на символы.

Функция MORECORE получает память от операционной системы. Детали того, как это осуществляется, меняются, конечно, от системы к системе. На системе UNIX точка входа SBRK(N) возвращает указатель на "N" дополнительных байтов памяти.(указатель удволетворяет всем ограничениям на выравнивание). Так как запрос к системе на выделение памяти является сравнительно дорогой операцией, мы не хотим делать это при каждом обращении к функции ALLOC. Поэтому функция MORECORE округляет затребованное число единиц до большего значения; этот больший блок будет затем разделен так, как необходимо. Масштабирующая величина является параметром, который может быть подобран в соответствии с необходимостью.

#DEFINE NALLOC 128 /*#UNITS TO ALLOCATE AT ONCE*/ STATIC HEADER *MORECORE(NU) /*ASK SYSTEM FOR MEMORY*/ UNSIGNED NU;

REGISTER CHAR *CP;

REGISTER HEADER *UP;

REGISTER INT RNU;

RNU=NALLOC*((NU+NALLOC-1)/NALLOC);

CP=SBRK(RNU*SIZEOF(HEADER));

IF ((INT)CP==-1) /*NO SPACE AT ALL*/ RETURN(NULL);

UP=(HEADER *)CP;

UP->S.SIZE=RNU;

FREE((CHAR *)(UP+1));

RETURN(ALLOCP);

Если больше не осталось свободного пространства, то функция SBRK возвращает "-1", хотя NULL был бы лучшим выбором. Для надежности сравнения "-1" должна быть преобразована к типу INT. Снова приходится многократно использовать явные преобразования (перевод) типов, чтобы обеспечить определенную независимость функций от деталей представления указателей на различных машинах.

И последнее — сама функция FREE. Начиная с ALLOCP, она просто просматривает свободный список в поиске места для введения свободного блока. Это место находится либо между двумя существующими блоками, либо в одном из концов списка. В любом случае, если освободившийся блок примыкает к одному из соседних, смежные блоки объединяются. Следить нужно только затем, чтобы указатели указывали на то, что нужно, и чтобы размеры были установлены правильно.

FREE(AP) /*PUT BLOCKE AP IN FREE LIST*/ CHAR *AP;

REGISTER HEADER *P, *G;

P=(HEADER*)AP-1; /*POINT TO HEADER*/ FOR (G=ALLOCP; !(P>G && P>G->S.PTR);G=G->S.PTR) IF (G>=G->S.PTR && (P>G \!\! PS.PTR)) BREAK; /*AT ONE END OR OTHER*/ IF (P+P->S.SIZE==G->S.PTR)\(/*JOIN TO UPPER NBR*/ P->S.SIZE += G->S.PTR->S.SIZE;

P->S.PTR = G->S.PTR->S.PTR;

\) ELSE P->S.PTR = G->S.PTR;

IF (G+G->S.SIZE==P) \( /*JOIN TO LOWER NBR*/ G->S.SIZE+=P->S.SIZE;

G->S.PTR=P->S.PTR;

\) ELSE ALLOCP = G;

Хотя распределение памяти по своей сути зависит от используемой машины, приведенная выше программа показывает, как эту зависимость можно регулировать и ограничить весьма небольшой частью программы. Использование TYPEDEF и UNION позволяет справиться с выравниванием (при условии, что функция SBRK обеспечивает подходящий указатель). Переводы типов организуют выполнение явного преобразования типов и даже справляются с неудачно разработанным системным интерфейсом. И хотя рассмотренные здесь подробности связаны с распределением памяти, общий подход равным образом применим и к другим ситуациям.

Упражнение 8-6.

Функция из стандартной библиотеки CALLOC(N,SIZE) возвращает указатель на "N" объектов размера SIZE, причем соответствующая память инициализируется на нуль. напишите программу для CALLOC, используя функцию ALLOC либо в качестве образца, либо как функцию, к которой происходит обращение.

Упражнение 8-7.

Функция ALLOC принимает затребованный размер, не проверяя его правдоподобности; функция FREE полагает, что тот блок, который она должна освободить, содержит правильное значение в поле размера. Усовершенствуйте эти процедуры, затратив больше усилий на проверку ошибок.

Упражнение 8-8.

Напишите функцию BFREE(P,N), которая включает произвольный блок "P" из "N" символов в список свободных блоков, управляемый функциями ALLOC и FREE. С помощью функции BFREE пользователь может в любое время добавлять в свободный список статический или внешний массив.

9. Приложение А: справочное руководство по языку 'C' 9.1. Введение Это руководство описывает язык 'с' для компьютеров DEC PDP-11, HONEYWELL 6000, IBM система/370 и INTERDATA 8/32. там, где есть расхождения, мы сосредотачиваемся на версии для PDP-11, стремясь в то же время указать детали, которые зависят от реализации. За малым исключением, эти расхождения непосредственно обусловлены основными свойствами используемого аппаратного оборудования; различные компиляторы обычно вполне совместимы.

10. Лексические соглашения Имеется шесть классов лексем: идентификаторы, ключевые слова, константы, строки, операции и другие разделители. Пробелы, табуляции, новые строки и комментарии (совместно, "пустые промежутки"), как описано ниже, игнорируются, за исключением тех случаев, когда они служат разделителями лексем. Необходим какойто пустой промежуток для разделения идентификаторов, ключевых слов и констант, которые в противном случае сольются.

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

10.1. Комментарии Комментарий открывается символами /* и заканчивается символами /*.

Комментарии не вкладываются друг в друга.

10.2. Идентификаторы (имена) Идентификатор — это последовательность букв и цифр; первый символ должен быть буквой. Подчеркивание _ считается буквой. Буквы нижнего и верхнего регистров различаются. значащими являются не более, чем первые восемь символов, хотя можно использовать и больше. На внешние идентификаторы, которые используются различными ассемблерами и загрузчиками, накладыватся более жесткие ограничения:

HONEYWELL INTERDATA 8/ 10.3. Ключевые слова Следующие идентификаторы зарезервированы для использования в качестве ключевых слов и не могут использоваться иным образом:

INT EXTERN ELSE

CHAR REGISTER FOR

FLOAT TYPEDEF DO

DOUBLE STATIC WHILE

STRUCT GOTO SWITCH

UNION RETURN CASE

LONG SIZEOF DEFAULT

SHORT BREAK ENTRY

UNSIGNED CONTINUE

Ключевое слово ENTRY в настоящее время не используется каким-либо компилятором;

оно зарезервировано для использования в будущем. В некоторых реализациях резервируется также слова FORTRAN и ASM 10.4. Константы Имеется несколько видов констант, которые перечислены ниже. В пункте 10. резюмируются характеристики аппаратных средств, которые влияют на размеры.

10.4.1. Целые константы Целая константа, состоящая из последовательности цифр, считается восьмеричной, если она начинается с 0 (цифра нуль), и десятичной в противном случае. Цифры 8 и 9 имеют восьмеричные значения 10 и 11 соответственно.

Последовательность цифр, которой предшествуют символы 0х (нуль, х-маленькое) или х-большое), рассматривается как шестнадцатиричное целое.

Шестнадцатиричные цифры включают буквы от а (маленькое) или а (большое) до F (маленькое) или F (большое) со значениями от 10 до 15. Десятичная константа, величина которой превышает наибольшее машинное целое со знаком, считается длинной; восмеричная или шестнадцатиричная константа, которое превышает наибольшее машинное целое без знака, также считается длинной.

10.4.2. Явные длинные константы Десятичная, восмеричная или шестнадцатиричная константа, за которой непосредственно следует L (эль-маленькое) или L (эль-большое), является длинной константой. Как обсуждается ниже, на некоторых машинах целые и длинные значения могут рассматриваться как идентичные.

10.4.3. Символьные константы Символьная константа — это символ, заключенный в одиночные кавычки, как, например, 'X'. Значением символьной константы является численное значение этого символа в машинном представлении набора символов.

Некоторые неграфические символы, одиночная кавычка ' и обратная косая черта \ могут быть представлены в соответствии со следующей таблицей условных последовательностей:

Условная последовательность \DDD состоит из обратной косой черты, за которой следуют 1,2 или 3 восмеричных цифры, которые рассмативаются как задающие значение желаемого символа. Специальным случаем этой конструкции является последовательность \0 (за нулем не следует цифра), которая определяет символ NUL.

если следующий за обратной косой чертой символ не совпадает с одним из указанных, то обратная косая черта игнорируется.

10.4.4. Плавающие константы Плавающая константа состоит из целой части, десятичной точки, дробной части, буквы E (маленькая) или E (большая) и целой экспоненты с необязательным знаком.

Как целая, так и дробная часть являются последовательностью цифр. Либо целая, либо дробная часть (но не обе) может отсутствовать; либо десятичная точка, либо е (маленькая) и экспонента (но не то и другое одновременно) может отсутствовать.

Каждая плавающая константа считается имеющей двойную точность.

10.5. Строки Строка — это последовательность символов, заключенная в двойные кавычки, как, наприимер,"...". Строка имеет тип "массив массивов" и класс памяти STATIC (см.

Пункт 4 ниже). Строка инициализирована указанными в ней символами. Все строки, даже идентично записанные, считаются различными. Компилятор помещает в конец каждой строки нулевой байт \0, с тем чтобы просматривающая строку программа могла определить ее конец. Перед стоящим внутри строки символом двойной кавычки " должен быть поставлен символ обратной косой черты \; кроме того, могут использоваться те же условия последовательности, что и в символьных константах. И последнее, обратная косая черта \, за которой непосредственно следует символ новой строки, игнорируется.

10.6. Характеристики аппаратных средств Следующая ниже таблица суммирует некоторые свойства аппаратного оборудования, которые меняются от машины к машине. Хотя они и влияют на переносимость программ, на практике они представляют маленькую проблему, чем это может казаться заранее.

ASCII ASCII EBCDIC ASCII

11. Синтаксическая нотация В используемой в этом руководстве синтаксической нотации синтаксические категории выделяются курсивом (прим. перев.: в настоящее время синтексические категории вместо курсивом выделяются подчеркиванием), а литерные слова и символы — жирным шрифтом. Альтернативные категории перечисляются на отдельных строчках. Необязательный символ, терминальный или нетерминальный, указывается индексом "необ", так что \( выражение --------- необ \) указывает на необязательное выражение, заключенное в фигурных скобках.

Синтаксис суммируется в пункте 18.

12. Что в имене тебе моем?

Язык "C" основывает интерпретацию идентификатора на двух признаках идентификатора: его классе памяти и его типе. Класс памяти определяет место и время хранения памяти, связанной с идентификатором; тип определяет смысл величин, находящихся в памяти, определенной под идентификатором.

Имеются четыре класса памяти: автоматическая, статическая, внешняя и регистровая. Автоматические переменные являются локальными для каждого вызова блока и исчезают при выходе из этого блока. Статические переменные являются локальными, но сохраняют свои значения для следующего входа в блок даже после того, как управление передается за пределы блока. Внешние переменные существуют и сохраняют свои значения в течение выполнения всей программы и могут использоваться для связи между функциями, в том числе и между независимо скомпилированными функциями. Регистровые переменные хранятся (ели это возможно) в быстрых регистрах машины; подобно автоматическим переменным они являются локальными для каждого блока и исчезают при выходе из этого блока.

В языке "C" предусмотрено несколько основных типов объектов:

объекты, написанные как символы (CHAR), достаточно велики, чтобы хранить любой член из соответствующего данной реализации внутреннего набора символов, и если действительный символ из этого набора символов хранится в символьной переменной, то ее значение эквивалентно целому коду этого символа. В символьных переменных можно хранить и другие величины, но реализация будет машиннозависимой.

Можно использовать до трех размеров целых, описываемых как SHORT INT, INT и LONG INT. Длинные целые занимают не меньше памяти, чем короткие, но в конкретной реализации может оказаться, что либо короткие целые, либо длинные целые, либо те и другие будут эквивалентны простым целым. "Простые" целые имеют естественный размер, предусматриваемый архиитектурой используемой машины;

другие размеры вводятся для удволетворения специальных потребностей.

Целые без знака, описываемые как UNSIGNED, подчиняются законам арифметики по модулю 2**N, где N — число битов в их представлении. (На PDP- длинные величины без знака не предусмотрены).

Плавающие одинарной точности (FLOAT) и плавающие двойной точности (DOUBLE) в некоторых реализациях могут быть синонимами.

интерпретированы как числа, эти типы будут называться арифметическими. типы CHAR и INT всех размеров совместно будут называться целочисленными. Типы FLOAT и DOUBLE совместно будут называться плавающими типами.

Кроме основных арифметических типов существует концептуально бесконечный класс производных типов, которые образуются из основных типов следующим образом:

• массивы объектов большинства типов;

• функции, которые возвращают объекты заданного типа;

• указатели на объекты данного типа;

• структуры, содержащие последовательность объектов • различных типов;

• объединения, способные содержать один из нескольких объектов различных типов.

Вообще говоря, эти методы построения объектов могут применяться рекурсивно.

13. Объекты и L-значения Объект является доступным обработке участком памяти; L-значение — это выражение, ссылающееся на объект. Очевидным примером выражения L-значения является идентификатор. Существуют операции, результатом которых являются Lзначения; если, например, E — выражение указанного типа, то *E является выражением L-значения, ссылающимся на объект E. Название "L-значение" происходит от выражения присваивания E1=E2, в котором левая часть должна быть выражением L-значения. При последующем обсуждении каждой операции будет указываться, ожидает ли она операндов L-значения и выдает ли она L-значение.

14. Преобразования Ряд операций может в зависимости от своих операндов вызывать преобразование значение операнда из одного типа в другой. В этом разделе объясняются результаты, которые следует ожидать от таких преобразований. В п.

14.6 Подводятся итоги преобразований, требуемые большинством обычных операций;

эти сведения дополняются необходимым образом при обсуждении каждой операции.

14.1. Символы и целые Символ или короткое целое можно использовать всюду, где можно использовать целое. Во всех случаях значение преобразуется к целому. Преобразование более короткого целого к более длинному всегда сопровождается знаковым расширением;

целые являются величинами со знаком. Осуществляется или нет знаковое расширение для символов, зависит от используемой машины, но гарантируется, что член стандартного набора символов неотрицателен. из всех машин, рассматриваемых в этом руководстве, только PDP-11 осуществляет знаковое расширение. область значений символьных переменных на PDP-11 меняется от -128 до 127; символы из набора ASC11 имеют положительные значения. Символьная константа, заданная с помощью восьмеричной условной последовательности, подвергается знаковому расширению и может оказаться отрицательной; например, '\377' имеет значение -1.

Когда более длинное целое преобразуется в более короткое или в CHAR, оно обрезается слева; лишние биты просто отбрасываются.

14.2. Типы FLOAT и DOUBLE Вся плавающая арифметика в "C" выполняется с двойной точностью каждый раз, когда объект типа FLOAT появляется в выражении, он удлиняется до DOUBLE посредством добавления нулей в его дробную часть. когда объект типа DOUBLE должен быть преобразован к типу FLOAT, например, при присваивании, перед усечением DOUBLE округляется до длины FLOAT.

14.3. Плавающие и целочисленные величины Преобразование плавающих значений к целочисленному типу имеет тенденцию быть до некоторой степени машинно-зависимым; в частности направление усечения отрицательных чисел меняется от машине к машине. Результат не определен, если значение не помещается в предоставляемое пространство.

Преобразование целочисленных значений в плавающие выполняется без осложнений. Может произойти некоторая потеря точности, если для результата не содержится достаточного количества битов.

14.4. Указатели и целые Целое или длинное целое может быть прибавлено к указателю или вычтено из него; в этом случае первая величина преобразуется так, как указывается в разделе описания операции сложения.

Два указателя на объекты одинакового типа могут быть вычтены; в этом случае результат преобразуется к целому, как указывается в разделе описания операции вычитания.

14.5. Целое без знака Всякий раз, когда целое без знака объединяется с простым целым, простое целое преобразуется в целое без знака и результат оказывается целым без знака. Значением является наименьшее целое без знака, соответствующее целому со знаком (по модулю 2**размер слова). В двоичном дополнительном представлении это преобразование является чисто умозрительным и не изменяет фактическую комбинацию битов.

Когда целое без знака преобразуется к типу LONG, значение результата совпадает со значением целого без знака. Таким образом, это преобразование сводится к добавлению нулей слева.

14.6. Арифметические преобразования Подавляющее большинство операций вызывает преобразование и определяет типы результата аналогичным образом. Приводимая ниже схема в дальнейшем будет называться "обычными арифметическими преобразованиями".

Сначала любые операнды типа CHAR или SHORT преобразуются в INT, а любые операнды типа FLOAT преобразуются в DOUBLE. Затем, если какойлибо операнд имеет тип DOUBLE, то другой преобразуется к типу DOUBLE, и это будет типом результата. В противном случае, если какой-либо операнд имеет тип LONG, то другой операнд преобразуется к типу LONG, и это и будет типом результата.

В противном случае, если какой-либо операнд имеет тип UNSIGNED, то другой операнд преобразуется к типу UNSIGNED, и это будет типом результата.

В противном случае оба операнда будут иметь тип INT, и это будет типом результата.

15. Выражения Старшинство операций в выражениях совпадает с порядком следования основных подразделов настоящего раздела, начиная с самого высокого уровня старшинства. Так, например, выражениями, указываемыми в качестве операндов операции + (п.15.4), Являются выражения, определенные в п.п.15.1-15.3. Внутри каждого подраздела операции имеет одинаковое старшинство. В каждом подразделе для описываемых там операций указывается их ассоциативность слева или справа.

Старшинство и ассоциативность всех операций в выражениях резюмируются в грамматической сводке в п.18.

В противном случае порядок вычислений выражений не определен. В частности, компилятор считает себя в праве вычислять подвыражения в том порядке, который он находит наиболее эффективным, даже если эти подвыражения приводят к побочным эффектам. Порядок, в котором происходят побочные эффекты, не специфицируется. Выражения, включающие коммутативные и ассоциативные операции ( *,+,&,!,^ ), могут быть переупорядочены произвольным образом даже при наличии круглых скобок; чтобы вынудить определенный порядок вычислений, в этом случае необходимо использовать явные промежуточные переменные.

При вычислении выражений обработка переполнения и проверка при делении являются машинно-зависимыми. Все существующие реализации языка "C" игнорируют переполнение целых; обработка ситуаций при делении на 0 и при всех особых случаях с плавающими числами меняется от машины к машине и обычно выполняется с помощью библиотечной функции.

15.1. Первичные выражения Первичные выражения, включающие ->, индексацию и обращения к функциям, группируются слева направо.

Первичное выражение: идентификатор константа строка (выражение) первичное-выражение [выражение] первичное-выражение (списоквыражений нео первичное-L-значение. Идентификатор первичное-выражение -> идентификатор список-выражений:

выражение список-выражений, выражение Идентификатор является первичным выражением при условии, что он описан подходящим образом, как это обсуждается ниже. тип идентификатора определяется его описанием. Если, однако, типом идентификатора является "массив...", то значением выражения, состоящего из этого идентификатора, является указатель на первый объект в этом массиве, а типом выражения будет "указатель на...". Более того, идентификатор массива не является выражением L-значения. подобным образом идентификатор, который описан как "функция, возвращающая...", за исключением того случая, когда он используется в позиции имени функции при обращении, преобразуется в "указатель на функцию, которая возвращает...".

Константа является первичным выражением. В зависимости от ее формы типом константы может быть INT, LONG или DOUBLE.

Строка является первичным выражением. Исходным ее типом является "массив символов"; но следуя тем же самым правилам, которые приведены выше для идентификаторов, он модифицируется в "указатель на символы", и результатом является указатель на первый символ строки. (имеется исключение в некоторых инициализаторах; см. П. 16.6.) Выражение в круглых скобках является первичным выражением, тип и значение которого идентичны типу и значению этого выражения без скобок. Наличие круглых скобок не влияет на то, является ли выражение L-значением или нет.

Первичное выражение, за которым следует выражение в квадратных скобках, является первичным выражением. Интуитивно ясно, что это выражение с индексом.

Обычно первичное выражение имеет тип "указатель на...", индексное выражение имеет тип INT, а типом результата является "...". Выражение E1[E2] по определению идентично выражению * ((E1) + (E2)). Все, что необходимо для понимания этой записи, содержится в этом разделе; вопросы, связанные с понятием идентификаторов и операций * и + рассматриваются в п.п. 15.1, 15.2 И 15. соответственно; выводы суммируются ниже в п. 22.3.

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

Первичное выражение должно быть типа "функция, возвращающая...", а результат обращения к функции имеет тип "...". Как указывается ниже, ранее не встречавщийся идентификатор, за которым непосредственно следует левая круглая скобка, считается описанным по контексту, как представляющий функцию, возвращающую целое; следовательно чаще всего встречающийся случай функции, возвращающей целое значение, не нуждается в описании.

Перед обращением любые фактические аргументы типа FLOAT преобразуются к типу DOUBLE, любые аргументы типа CHAR или SHORT преобразуются к типу INT, и, как обычно, имена массивов преобразуются в указатели. Никакие другие преобразования не выполняются автоматически; в частности, не сравнивает типы фактических аргументов с типами формальных аргументов. Если преобразование необходимо, используйте явный перевод типа (CAST); см. П.п. 15.2, 16.7.

При подготовке к вызову функции делается копия каждого фактического параметра; таким образом, все передачи аргументов в языке "C" осуществляются строго по значению. функция может изменять значения своих формальных параметров, но эти изменения не влияют на значения фактических параметров. С другой строны имеется возможность передавать указатель при таком условии, что функция может изменять значение объекта, на который этот указатель указывает.

Порядок вычисления аргументов в языке не определен; обратите внимание на то, что различные компиляторы вычисляют по разному.

Допускаются рекурсивные обращения к любой функции.

Первичное выражение, за которым следует точка и идентификатор, является выражением. Первое выражение должно быть L-значением, именующим структуру или объединение, а идентификатор должен быть именем члена структуры или объединения. Результатом является L-значение, ссылающееся на поименованный член структуры или объединения.

Первичное выражение, за которым следует стрелка (составленная из знаков — и >) и идентификатор, является выражением. первое выражение должно быть указателем на структуру или объединение, а идентификатор должен именовать член этой структуры или объединения. Результатом является L-значение, ссылающееся на поименованный член структуры или объединения, на который указывает указательное выражение.

Следовательно, выражение E1->MOS является тем же самым, что и выражение (*E1).MOS. Структуры и объединения рассматриваются в п. 16.5. Приведенные здесь правила использования структур и объединений не навязываются строго, для того чтобы иметь возможность обойти механизм типов. См. П. 22.1.

15.2. Унарные операции Выражение с унарными операциями группируется справо налево.

Унарное-выражение:

L-значение -имя-типа) выражение Унарная операция * означает косвенную адресацию: выражение должно быть указателем, а результатом является L-значение, ссылающееся на тот объект, на который указывает выражение. Если типом выражения является "указатель на...", то типом результата будет "...".

Результатом унарной операции & является указатель на объект, к которому ссылается L-значение. Если L-значение имеет тип "...", то типом результата будет "указатель на...".

Результатом унарной операции — (минус) является ее операнд, взятый с противоположным знаком. Для величины типа UNSIGNED результат получается вычитанием ее значения из 2**N (два в степени N), где N-число битов в INT. Унарной операции + (плюс) не существует.

Результатом операции логического отрицания ! Является 1, если значение ее операнда равно 0, и 0, если значение ее операнда отлично от нуля. Результат имеет тип INT. Эта операция применима к любому арифметическому типу или указателям.

Операция \^ дает обратный код, или дополнение до единицы, своего операнда.

Выполняются обычные арифметические преобразования. Операнд должен быть целочисленного типа.

Объект, на который ссылается операнд L-значения префиксной операции ++, увеличивается. значением является новое значение операнда, но это не L-значение.

Выражение ++х эквивалентно х+=1. Информацию о преобразованиях смотри в разборе операции сложения (п. 15.4) и операции присваивания (п.15.14).

Префиксная операция — аналогична префиксной операции ++, но приводит к уменьшению своего операнда L-значения.

При применении постфиксной операции ++ к L-значению результатом является значение объекта, на который ссылается L-значение. После того, как результат принят к сведению, объект увеличивается точно таким же образом, как и в случае префиксной операции ++. Результат имеет тот же тип, что и выражение L-значения.

При применении постфиксной операции — к L-значению результатом является значение объекта, на который ссылается L-значение. После того, как результат принят к сведению, объект уменьшается точно таким же образом, как и в случае префиксной операции --. Результат имеет тот же тип, что и выражение L-значения.

Заключенное в круглые скобки имя типа данных, стоящее перед выражением, вызывает преобразование значения этого выражения к указанному типу. Эта конструкция называется перевод (CAST). Имена типов описываются в п. 16.7.

Операция SIZEOF выдает размер своего операнда в байтах. (Понятие байт в языке не определено, разве только как значение операции SIZEOF. Однако во всех существующих реализациях байтом является пространство, необходимое для хранения объекта типа CHAR). При применении к массиву результатом является полное число байтов в массиве. Размер определяется из описаний объектов в выражении. Это выражение семантически является целой константой и может быть использовано в любом месте, где требуется константа. Основное применение эта операция находит при связях с процедурами, подобным распределителям памяти, и в системах ввода- вывода.

Операция SIZEOF может быть также применена и к заключенному в круглые скобки имени типа. В этом случае она выдает размер в байтах объекта указанного типа.

Конструкция SIZEOF (тип) рассматривается как целое, так что выражение SIZEOF (тип) — 2 эквивалентно выражению (SIZEOF (тип)9 — 2.

15.3. Мультипликативные операции Мультипликативные операции *, /, и % группируются слева направо.

Выполняются обычные арифметические преобразования.

Мультипликативное-выражение: выражение * выражение выражение / выражение выражение % выражение Бинарная операция * означает умножение. Операция * ассоциативна, и выражения с несколькими умножениями на одном и том же уровне могут быть перегруппированы компилятором.

Бинарная операция / означает деление. При делении положительных целых осуществляется усечение по направлению к нулю, но если один из операндов отрицателен, то форма усечения зависит от используемой машины. На всех машинах, охватываемых настоящим руководством, остаток имеет тот же знак, что и делимое.

Всегда справедливо, что (A/B)*B+A% B равно A (если B не равно 0).

Бинарная операция % выдает остаток от деления первого выражения на второе.

Выполняются обычные арифметические преобразования. Операнды не должны быть типа FLOAT.

15.4. Аддитивные операции Аддитивные операции + и — группируются слева направо. выполняются обычные арифметические преобразования. Для каждой операции имеются некоторые дополнительные возможности, связанные с типами операндов.

Аддитивное-выражение: выражение + выражение выражение — выражение Результатом операции + является сумма операндов. Можно складывать указатель на объект в массиве и значение любого целочисленного типа. во всех случаях последнее преобразуется в адресное смещение посредством умножения его на длину объекта, на который указывает этот указатель. Результатом является указатель того же самого типа, что и исходный указатель, который указывает на другой объект в том же массиве, смещенный соответствующим образом относительно первоначального объекта. Таким образом, если P является указателем объекта в массиве, то выражение P+1 является указателем на следующий объект в этом массиве.

Никакие другие комбинации типов для указателей не разрешаются.

Операция + ассоциативна, и выражение с несколькими сложениями на том же самом уровне могут быть переупорядочены компилятором.

Результатом операции — является разность операндов. Выполняются обычные арифметические преобразования. Кроме того, из указателя может быть вычтено значение любого целочисленного типа, причем, проводятся те же самые преобразования, что и при операции сложения.

Если вычитаются два указателя на объекты одинакового типа, то результат преобразуется (делением на длину объекта) к типу INT, представляя собой число объектов, разделяющих указываемые объекты. Если эти указатели не на объекты из одного и того же массива, то такое преобразование, вообще говоря, даст неожиданные результаты, потому что даже указатели на объекты одинакового типа не обязаны отличаться на величину, кратную длине объекта.

15.5. Операции сдвига Операции сдвига > группируются слева направо. Для обеих операций проводятся обычные арифметические преобразования их операндов, каждый из которых должен быть целочисленного типа. Затем правый операнд преобразуется к типу INT; результат имеет тип левого операнда. Результат не определен, если правый операнд отрицателен или больше или равен, чем длина объекта в битах.

Выражение-сдвига: выражение > выражение Значением выражения E1E2 является E1, сдвинутое вправо на E2 битовых позиций. Если E1 имеет тип UNSIGNE, то сдвиг вправо гарантированно будет логическим (заполнение нулем); в противном случае сдвиг может быть (и так и есть на PDP-11) арифметическим (освобождающиеся биты заполняются копией знакового бита).

15.6. Операции отношения Операции отношения группируются слева направо, но этот факт не очень полезен; выражение A (больше), = (больше или равно) все дают 0, если указанное отношение ложно, и 1, если оно истинно. Результат имеет тип ITN. Выполняются обычные арифметические преобразования. Могут сравниваться два указателя; результат зависит от относительного расположения указываемых объектов в адресном пространстве. Сравнение указателей переносимо только в том случае, если указатели указывают на объекты из одного и того же массива.

15.7. Операции равенства Выражение-равенства: выражение == выражение выражение != выражение Операции == (равно) и != (не равно) в точности аналогичны операциям отношения, за исключением того, что они имеют более низкий уровень старшинства. (Поэтому значение выражения AB)? A:B;

RETURN((M>C)? M:C);

Здесь INT — спецификатор-типа, MAX(A,B,C) — описатель-функции, INT A,B,C; — список-описаний формальных параметров, \(... \) — Блок, содержащий текст оператора.

В языке "C" все фактические параметры типа FLOAT преобразуются к типу DOUBLE, так что описания формальных параметров, объявленных как FLOAT, приспособлены прочесть параметры типа DOUBLE. Аналогично, поскольку ссылка на массив в любом контексте (в частности в фактическом параметре) рассматривается как указатель на первый элемент массива, описания формальных параметров вила "массив..." приспособлены прочесть : "указатель на...". И наконец, поскольку структуры, объединения и функции не могут быть переданы функции, бессмысленно описывать формальный параметр как структуру, объединение или функцию (указатели на такие объекты, конечно, допускаются).

18.2. Внешние определения данных Внешнее определение данных имеет форму определение-данных:

описание Классом памяти таких данных может быть EXTERN (в частности, по умолчанию) или STATIC, но не AUTO или REGISTER.

19. Правила, определяющие область действия Вся C-программа необязательно компилируется одновременно; исходный текст программы может храниться в нескольких файлах и ранее скомпилированные процедуры могут загружаться из библиотек. Связь между функциями может осуществляться как через явные обращения, так и в результате манипулирования с внешними данными.

Поэтому следует рассмотреть два вида областей действия: во-первых, ту, которая может быть названа лексической областью действия идентификатора и которая по существу является той областью в программе, где этот идентификатор можно использовать, не вызывая диагностического сообщения "неопределенный идентификатор"; и во-вторых, область действия, которая связана с внешними идентификаторами и которая характеризуется правилом, что ссылки на один и тот же внешний идентификатор являются ссылками на один и тот же объект.

19.1. Лексическая область действия Лексическая область действия идентификаторов, описанных во внешних определениях, простирается от определения до конца исходного файла, в котором он находится. Лексическая область действия идентификаторов, являющихся формальными параметрами, распространяется на ту функцию, к которой они относятся. Лексическая область действия идентификаторов, описанных в начале блока, простирается до конца этого блока. Лексической областью действия меток является та функция, в которой они находятся.

Поскольку все обращения на один и тот же внешний идентификатор обращаются к одному и тому же объекту (см. П. 19.2), Компилятор проверяет все описания одного и того же внешнего идентификатора на совместимость; в действительности их область действия распространяется на весь файл, в котором они находятся.

Во всех случаях, однако, есть некоторый идентификатор, явным образом описан в начале блока, включая и блок, который образует функцию, то действие любого описания этого идентификатора вне блока приостанавливается до конца этого блока.

Напомним также (п. 16.5), Что идентификаторы, соответствующие обычным переменным, с одной стороны, и идентификаторы, соответствующие членам и ярлыкам структур и объединений, с другой стороны, формируют два непересекающихся класса, которые не вступают в противоречие. Члены и ярлыки подчиняются тем же самым правилам определения областей действия, как и другие идентификаторы. Имена, специфицируемые с помощью TYPEDEF, входят в тот же класс, что и обычные идентификаторы. Они могут быть переопределены во внутренних блоках, но во внутреннем описании тип должен быть указан явно:

TYPEDEF FLOAT DISTANCE;

AUTO INT DISTANCE;

Во втором описании спецификатор типа INT должен присутствовать, так как в противном случае это описание будет принято за описание без описателей с типом DISTANCE (прим. Автора: согласитесь, что лед здесь тонок.).

19.2. Область действия внешних идентификаторов Если функция ссылается на идентификатор, описанный как EXTERN, то где-то среди файлов или библиотек, образующих полную программу, должно содержаться внешнее определение этого идентификатора. Все функции данной программы, которые ссылаются на один и тот же внешний идентификатор, ссылаются на один и тот же объект, так что следует позаботиться, чтобы специфицированные в этом определении тип и размер были совместимы с типом и размером, указываемыми в каждой функции, которая ссылается на эти данные.

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

Следовательно, в состоящей из многих файлов программе внешнее определение идентификатора, не содержащее спецификатора EXTERN, должно появляться ровно в одном из этих файлов. любые другие файлы, которые желают дать внешнее определение этого идентификатора, должны включать в это определение слово EXTERN. Идентификатор может быть инициализирован только в том описании, которое приводит к выделению памяти.

Идентификаторы, внешнее определение которых начинается со слова STATIC, недоступны из других файлов. Функции могут быть описаны как STATIC.

20. Строки управления компилятором Компилятор языка "C" содержит препроцессор, который позволяет осуществлять макроподстановки, условную компиляцию и включение именованных файлов.

Строки, начинающиеся с #, общаются с этим препроцессором. Синтаксис этих строк не связан с остальным языком; они могут появляться в любом месте и их влияние распространяется (независимо от области действия) до конца исходного программного файла.

20.1. Замена лексем Управляющая компилятором строка вида #DEFINE идентификатор строка-лексем (Обратите внимание на отсутствие в конце точки с запятой) приводит к тому, что препроцессор заменяет последующие вхождения этого идентификатора на указанную строку лексем. Строка вида #DEFINE (идентификатор,...,идентификатор)строка лексем где между первым идентификатором и открывающейся скобкой ( нет пробела, представляет собой макроопределение с аргументами. Последующее вхождение первого идентификатора, за которым следует открывающая скобка '(', последовательность разделенных запятыми лексем и закрывающая скобка ')', заменяются строкой лексем из определения. каждое вхождение идентификатора, упомянутого в списке формальных параметров в определении, заменяется соответствующей строкой лексем из обращения. Фактическими аргументами в обращении являются строки лексем, разделенные запятыми; однако запятые, входящие в закавыченные строки или заключенные в круглые скобки, не разделяют аргументов. Количество формальных и фактических параметров должно совпадать.

Текст внутри строки или символьной константы не подлежит замене.

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

Описываемая возможность особенно полезна для определения "объявляемых констант", как, например, #DEFINE TABSIZE INT TABLE[TABSIZE];

Управляющая строка вида #UNDEF идентификатор приводит к отмене препроцессорного определения данного идентификатора.

20.2. Включение файлов Строка управления компилятором вида #INCLUDE "FILENAME" приводит к замене этой строки на все содержимое файла с именем FILENAME. Файл с этим именем сначала ищется в справочнике начального исходного файла, а затем в последовательности стандартных мест. В отличие от этого управляющая строка вида #INCLUDE ищет файл только в стандартных местах и не просматривает справочник исходного файла.

Строки #INCLUDE могут быть вложенными.

20.3. Условная компиляция Строка управления компилятором вида #IF константное выражение проверяет, отлично ли от нуля значение константного выражения (см. П. 15).

Управляющая строка вида #IF DEF идентификатор проверяет, определен ли этот идентификатор в настоящий момент в препроцессоре, т.е. Определен ли этот идентификатор с помощью управляющей строки #DEFINE.

21. Неявные описания Не всегда является необходимым специфицировать и класс памяти и тип идентификатора в описании. Во внешних определениях и описаниях формальных параметров и членов структур класс памяти определяется по контексту. Если в находящемся внутри функции описании не указан тип, а только класс памяти, то предполагается, что идентификатор имеет тип INT; если не указан класс памяти, а только тип, то идентификатор предполагается описанным как AUTO. Исключение из последнего правила дается для функций, потому что спецификатор AUTO для функций является бессмысленным (язык "C" не в состоянии компилировать программу в стек); если идентификатор имеет тип "функция, возвращающая...", то он предполагается неявно описанным как EXTERN.

Входящий в выражение и неописанный ранее идентификатор, за которым следует скобка (, считается описанным по контексту как "функция, возвращающая INT".

22. Снова о типах В этом разделе обобщаются сведения об операциях, которые можно применять только к объектам определенных типов.

22.1. Структуры и объединения Только две вещи можно сделать со структурой или объединением: назвать один из их членов (с помощью операции) или извлечь их адрес ( с помощью унарной операции &). Другие операции, такие как присваивание им или из них и передача их в качестве параметров, приводят к сообщению об ошибке. В будущем ожидается, что эти операции, но не обязательно какие-либо другие, будут разрешены.

В п. 15.1 Говорится, что при прямой или косвенной ссылке на структуру (с помощью. Или ->) имя справа должно быть членом структуры, названной или указанной выражением слева. Это ограничение не навязывается строго компилятором, чтобы дать возможность обойти правила типов. В действительности перед '.' допускается любое L-значение и затем предполагается, что это L-значение имеет форму структуры, для которой стоящее справа имя является членом. Таким же образом, от выражения, стоящего перед '->', требуется только быть указателем или целым. В случае указателя предполагается, что он указывает на структуру, для которой стоящее справа имя является членом. В случае целого оно рассматривается как абсолютный адрес соответствующей структуры, заданный в единицах машинной памяти.

Такие структуры не являются переносимыми.

22.2. Функции Только две вещи можно сделать с функцией: вызвать ее или извлечь ее адрес.

Если имя функции входит в выражение не в позиции имени функции, соответствующей обращению к ней, то генерируется указатель на эту функцию.

Следовательно, чтобы передать одну функцию другой, можно написать INT F();

G(F);

Тогда определение функции G могло бы выглядеть так:

G(FUNCP) INT(*FUNCP)();

(*FUNCP)();

Обратите внимание, что в вызывающей процедуре функция F должна быть описана явно, потому что за ее появлением в G(F) не следует скобка (.

22.3. Массивы, указатели и индексация Каждый раз, когда идентификатор, имеющий тип массива, появляется в выражении, он преобразуется в указатель на первый член этого массива. Из-за этого преобразования массивы не являются L-значениями. По определению операция индексация [] интерпретируется таким образом, что E1[E2] считается идентичным выражению *((е1)+(е2)). Согласно правилам преобразований, применяемым при операции +, если E1 — массив, а е2 — целое, то е1[е2] ссылается на е2-й член массива е1. Поэтому несмотря на несимметричный вид операция индексации является коммутативной.

В случае многомерных массивов применяется последовательное правило. Если е является N-мерным массивом размера I*J*...*K, то при появлении в выражении е преобразуется в указатель на (N-1)-мерный массив размера J*...*K. Если операция * либо явно, либо неявно, как результат индексации, применяется к этому указателю, то результатом операции будет указанный (N-1)-мерный массив, который сам немедленно преобразуется в указатель.

Рассмотрим, например, описание INT X[3][5];

Здесь X массив целых размера 3*5. При появлении в выражении X преобразуется в указатель на первый из трех массивов из 5 целых. В выражении X[I], которое эквивалентно *(X+I), сначала X преобразуется в указатель так, как описано выше; затем I преобразуется к типу X, что вызывает умножение I на длину объекта, на который указывает указатель, а именно на 5 целых объектов. Результаты складываются, и применение косвенной адресации дает массив (из 5 целых), который в свою очередь преобразуется в указатель на первое из этих целых. Если в выражение входит и другой индекс, то таже самая аргументация применяется снова; результатом на этот раз будет целое.

Из всего этого следует, что массивы в языке "C" хранятся построчно ( последний индекс изменяется быстрее всего) и что первый индекс в описании помогает определить общее количество памяти, требуемое для хранения массива, но не играет никакой другой роли в вычислениях, связанных с индексацией.

22.4. Явные преобразования указателей Разрешаются определенные преобразования, с использованием указателей, но они имеют некоторые зависящие от конкретной реализации аспекты. Все эти преобразования задаются с помощью операции явного преобразования типа; см. П.

15.2 и 16.7.

Указатель может быть преобразован в любой из целочисленных типов, достаточно большой для его хранения. Требуется ли при этом INT или LONG, зависит от конкретной машины. Преобразующая функция также является машиннозависимой, но она будет вполне естественной для тех, кто знает структуру адресации в машине. Детали для некоторых конкретных машин приводятся ниже.

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

Указатель на один тип может быть преобразован в указатель на другой тип. Если преобразуемый указатель не указывает на объекты, которые подходящим образом выравнены в памяти, то результирующий указатель может при использовании вызывать ошибки адресации. Гарантируется, что указатель на объект заданного размера может быть преобразован в указатель на объект меньшего размера и снова обратно, не претерпев при этом изменения.

Например, процедура распределения памяти могла бы принимать запрос на размер выделяемого объекта в байтах, а возвращать указатель на символы; это можно было бы использовать следующим образом.

EXTERN CHAR *ALLOC();

DOUBLE *DP;

DP=(DOUBLE*) ALLOC(SIZEOF(DOUBLE));

*DP=22.0/7.0;

Функция ALLOC должна обеспечивать (машинно-зависимым способом), что возвращаемое ею значение будет подходящим для преобразования в указатель на DOUBLE; в таком случае использование этой функции будет переносимым.

Представление указателя на PDP-11 соответствует 16-битовому целому и измеряется в байтах. Объекты типа CHAR не имеют никаких ограничений на выравнивание; все остальные объекты должны иметь четные адреса.

На HONEYWELL 6000 указатель соответствует 36-битовому целому; слову соответствует 18 левых битов и два непосредственно примыкающих к ним справа бита, которые выделяют символ в слове. Таким образом, указатели на символы измеряются в единицах 2 в степени 16 байтов; все остальное измеряется в единицах 2 в степени 18 машинных слов. Величины типа DOUBLE и содержащие их агрегаты должны выравниваться по четным адресам слов (0 по модулю 2 в степени 19). Эвм IBM 370 и INTERDATA 8/32 сходны между собой. На обеих машинах адреса измеряются в байтах; элементарные объекты должны быть выровнены по границе, равной их длине, так что указатели на SHORT должны быть кратны двум, на INT и FLOAT — четырем и на DOUBLE — восьми. Агрегаты выравниваются по самой строгой границе, требуемой каким-либо из их элементов.

23. Константные выражения В нескольких местах в языке "C" требуются выражения, которые после вычисления становятся константами: после вариантного префикса CASE, в качестве границ массивов и в инициализаторах. В первых двух случаях выражение может содержать только целые константы, символьные константы и выражения SIZEOF, возможно связанные либо бинарными операциями либо унарными операциями либо тернарной операцией?:

Круглые скобки могут использоваться для группировки, но не для обращения к функциям.

В случае инициализаторов допускается большая (ударение на букву о) свобода;

кроме перечисленных выше константных выражений можно также применять унарную операцию & к внешним или статическим объектам и к внешним или статическим массивам, имеющим в качестве индексов константное выражение.

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

24. Соображения о переносимости Некоторые части языка "C" по своей сути машинно-зависимы. Следующие ниже перечисление потенциальных трудностей хотя и не являются всеобъемлющими, но выделяет основные из них.

Как показала практика, вопросы, целиком связанные с аппаратным оборудованием, такие как размер слова, свойства плавающей арифметики и целого деления, не представляют особенных затруднений. Другие аспекты аппаратных средств находят свое отражение в различных реализациях. Некоторые из них, в частности, знаковое расширение (преобразующее отрицательный символ в отрицательное целое) и порядок, в котором помещаются байты в слове, представляют собой неприятность, которая должна тщательно отслеживаться. Большинство из остальных проблем этого типа не вызывает сколько-нибудь значительных затруднений.

Число переменных типа REGISTER, которое фактически может быть помещено в регистры, меняется от машины к машине, также как и набор допустимых для них типов. Тем не менее все компиляторы на своих машинах работают надлежащим образом; лишние или недопустимые регистровые описания игнорируются.

Некоторые трудности возникают только при использовании сомнительной практики программирования. Писать программы, которые зависят от каких- либо этих свойств, является чрезвычайно неразумным.

Языком не указывается порядок вычисления аргументов функций; они вычисляются справа налево на PDP-11 и VAX-11 и слева направо на остальных машинах. порядок, в котором происходят побочные эффекты, также не специфицируется.

Так как символьные константы в действительности являются объектами типа INT, допускается использование символьных констант, состоящих из нескольких символов. Однако, поскольку порядок, в котором символы приписываются к слову, меняется от машины к машине, конкретная реализация оказывается весьма машинно-зависимой.

Присваивание полей к словам и символов к целым осуществляется справо налево на PDP-11 и VAX-11 и слева направо на других машинах. эти различия незаметны для изолированных программ, в которых не разрешено смешивать типы (преобразуя, например, указатель на INT в указатель на CHAR и затем проверяя указываемую память), но должны учитываться при согласовании с накладываемыми извне схемами памяти.

Язык, принятый на различных компиляторах, отличается только незначительными деталями. Самое заметное отличие состоит в том, что используемый в настоящее время компилятор на PDP-11 не инициализирует структуры, которые содержат поля битов, и не допускает некоторые операции присваивания в определенных контекстах, связанных с использованием значения присваивания.

25. Анахронизмы Так как язык "C" является развивающимся языком, в старых программах можно встретить некоторые устаревшие конструкции. Хотя большинство версий компилятора поддерживает такие анахронизмы, они в конце концов исчезнут, оставив за собой только проблемы переносимости.

В ранних версиях "C" для проблем присваивания использовалась форма =ON, а не ON=, приводя к двусмысленностям, типичным примером которых является где X фактически уменьшается, поскольку операции = и — примыкают друг к другу, но что вполне могло рассматриваться и как присваивание -1 к X.

Синтаксис инициализаторов изменился: раньше знак равенства, с которого начинается инициализатор, отсутствовал, так что вместо INT X = 1;

использовалось INT X 1;

изменение было внесено из-за инициализации INT F (1+2) которая достаточно сильно напоминает определение функции, чтобы смутить компиляторы.

26. Сводка синтаксических правил Эта сводка синтаксиса языка "C" предназначена скорее для облегчения понимания и не является точной формулировкой языка.

26.1. Выражения Основными выражениями являются следующие:

выражение:

первичное-выражение * выражение & выражение - выражение ! Выражение \^ выражение ++ L-значение -- L-значение L-значение ++ L-значение — SIZEOF выражение (имя типа) выражение выражение бинарная-операция выражение выражение? Выражение : выражение L-значение выражение первичное выражение:

идентификатор константа строка (выражение) первичное-выражение (список выражений необ) первичное-выражение [выражение] L-значение. Идентификатор первичное выражение -> идентификатор Идентификатор первичное-выражение -> идентификатор * выражение (L-значение) Операции первичных выражений имеют самый высокий приоритет и группируются слева направо. Унарные операции * & — ! \^ ++ — SIZEOF(Имя типа) имеют более низкий приоритет, чем операции первичных выражений, но более высокий, чем приоритет любой бинарной операции. Эти операции группируются справа налево. Все бинарные операции и условная операция (прим. Перевод.:

условная операция группируется справа налево; это изменение внесено в язык в г.) группируются слева направо и их приоритет убывает в следующем порядке:

Бинарные операции:

+Все операции присваивания имеют одинаковый приоритет и группируются справа налево.

Операции присваивания:



Pages:     | 1 ||


Похожие работы:

«Бюджетное образовательное учреждение Омской области Центр повышения квалификации работников здравоохранения Современные аспекты работы среднего медицинского персонала Бюджетное образовательное учреждение Омской области Центр повышения квалификации работников здравоохранения Медицинская сестра должна иметь квалификацию троякого ряда: научную – для понимания болезни, сердечную – для понимания больного, техническую – для ухода за больными. Флоренс Найтингейл Разделы: Разделы 1. Организация...»

«Содержание Пояснительная записка..3 1. Содержание учебного материала..4 2. Результаты образования..9 3. Формы оценки достижения результатов..10 4. Перечень учебно-методических средств обучения.10 5. Учебно-тематический план..11 6. Пояснительная записка Данная рабочая программа составлена на основании: стандарта среднего (полного) общего образования по географии (базовый уровень) 2004 г. примерной программы для среднего (полного) общего образования по географии (базовый уровень) 2004 г. Сборник...»

«ПОРТФОЛИО (портфель личных достижений) Учителя информатики и ИКТ: Королевой Ольги Анатольевны МОУ Киришская средняя общеобразовательная школа № 8 Содержание Содержание РАЗДЕЛ 1. Общие сведения Личные данные Образование Профессиональный путь Курсы повышения квалификации и профессиональная переподготовка Аттестация Поощрения / Награды РАЗДЕЛ 2. Результаты педагогической деятельности Итоговые результаты Результаты ЕГЭ Выпускники, окончившие школу с золотой и серебряной медалью Учащиеся,...»

«Учебно-методическое обеспечение. Теоретическое отделение. Программа Предмет Класс Учебники и учебные пособия Программа Министерства 1–7 Современная гармония. Программа курса и методическое пособие. Сольфеджио 1 культуры СССР для муз. Повышенный уровень. 2002 г. отделения школы искусств Сольфеджио. Программа. Т.А. Калужская. 1984 г. 1 (1984 г.) И.Левит. Программа. Сольфеджио. Опыт работы. 2005 г. 1 Упражнения на фортепиано в курсе гармонии. Н. Соловьева. - М., 2002 г. Тематический план по...»

«Международный консорциум Электронный университет Московский государственный университет экономики, статистики и информатики Евразийский открытый институт Е.С. Соколова Бухгалтерский (финансовый) учет Учебное пособие Москва 2007 1 УДК 657 ББК 65.052 С 594 Соколова Е.С. БУХГАЛТЕРСКИЙ (ФИНАНСОВЫЙ) УЧЕТ: Учебное пособие / Московский государственный университет экономики, статистики и информатики. – М.: МЭСИ, 2007. – 197 с. ISBN 5-374-00023-3 © Соколова Е.С., 2007 © Московский государственный...»

«МИНИСТЕРСТВО НАРОДНОГО ОБРАЗОВАНИЯ РЕСПУБЛИКИ УЗБЕКИСТАН РЕСПУБЛИКАНСКИЙ ЦЕНТР ОБРАЗОВАНИЯ АТТЕСТАЦИОННЫЕ МАТЕРИАЛЫ И МЕТОДИЧЕСКИЕ РЕКОМЕНДАЦИИ ПО ПРЕДМЕТАМ: РОДНОЙ ЯЗЫК, ИНОСТРАННЫЙ ЯЗЫК, ФИЗИКА, УЗБЕКСКИЙ ЯЗЫК, ИНФОРМАТИКА, ГЕОГРАФИЯ, БИОЛОГИЯ И ОСНОВЫ ГОСУДАРСТВА И ПРАВО НА 2013–2014 УЧЕБНЫЙ ГОД (по переводным экзаменам 7-8 классах общеобразовательных школ) Издательско-полиграфический творческий дом имени Гафура Гуляма Ташкент–2014 Аттестационные материалы рассмотрены и утверждены...»

«ФЕДЕРАЛЬНОЕ АГЕНТСТВО ПО ОБРАЗОВАНИЮ ГОУВПО ПЕРМСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ Кафедра новейшей истории России Корниенко С.И. Учебно-методический комплекс по дисциплине СОЦИОКУЛЬТУРНАЯ ДИНАМИКА РОССИЙСКОГО ОБЩЕСТВА В ХХ ВЕКЕ (Ч. 1; Ч. 2) Направление: 030600.62 История Согласовано: Рекомендовано кафедрой: Учебно-методическое управление Протокол № _2011 г. _2011 г. Зав. кафедрой _ Пермь 2011 Автор-составитель: Корниенко Сергей Иванович, доктор исторических наук, профессор Учебно-методический...»

«МИНИСТЕРСТВО СЕЛЬСКОГО ХОЗЯЙСТВА РОССИЙСКОЙ ФЕДЕРАЦИИ Федеральное государственное бюджетное образовательное учреждение высшего профессионального образования КУБАНСКИЙ ГОСУДАРСТВЕННЫЙ АГРАРНЫЙ УНИВЕРСИТЕТ Кафедра микробиологии, эпизоотологии и вирусологии Государственное управление ветеринарии Краснодарского края Государственное учреждение Краснодарского края Кропоткинская краевая ветеринарная лаборатория А.А. ШЕВЧЕНКО, О. Ю. ЧЕРНЫХ, Л.В. ШЕВЧЕНКО, Г.А. ДЖАИЛИДИ, Д.Ю. ЗЕРКАЛЕВ. Е.А. ГОРПИНЧЕНКО...»

«ГОСУДАРСТВЕННОЕ ОБРАЗОВАТЕЛЬНОЕ УЧРЕЖДЕНИЕ ВЫСШЕГО ПРОФЕССИОНАЛЬНОГО ОБРАЗОВАНИЯ КАЗАНСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ ИМ. В.И. УЛЬЯНОВА-ЛЕНИНА Электронные библиотеки научных и образовательных ресурсов. Учебно-методическое пособие Абросимов А.Г. Лазарева Ю.И. Казань 2008 Электронные библиотеки научных и образовательных ресурсов. Учебно-методическое пособие по направлению Электронные образовательные ресурсы. - Казань: КГУ, 2008. Учебно-методическое пособие публикуется по решению...»

«Министерство образования и науки Украины ОДЕССКИЙ НАЦИОНАЛЬНЫЙ ПОЛИТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ АТОМНЫЕ ЭЛЕКТРИЧЕСКИЕ СТАНЦИИ Учебное пособие для студентов специальности 8.090502 Атомная энергетика Одесса ОНПУ 2010 Министерство образования и науки Украины ОДЕССКИЙ НАЦИОНАЛЬНЫЙ ПОЛИТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ Киров В.С. АТОМНЫЕ ЭЛЕКТРИЧЕСКИЕ СТАНЦИИ Учебное пособие для студентов специальности 8.090502 Атомная энергетика Утверждено на заседании кафедры АЭС ИЭКСУ ОНПУ Протокол №2 от 28.10.2010 г. Одесса...»

«Институт управления, бизнеса и технологий. Калужский государственный университет им. К.Э. Циолковского Среднерусский научный центр Санкт-Петербургского отделения Международной академии наук высшей школы ОСОБЕННОСТИ СТАНОВЛЕНИЯ И РАЗВИТИЯ ИНВЕСТИЦИОННЫХ ПРОЦЕССОВ В РФ Крутиков В.К., Дорожкина Т.В., Зайцев Ю.В., Мельниченко Т.Ю. Учебно-методическое пособие КАЛУГА - 2012 ББК 65 К 84 Рецензенты: Г.А. Александров, доктор экономических наук, профессор, академик РАЕН И.С. Санду, доктор экономических...»

«Книгообеспеченность кафедры бухгалтерского учета, анализа и аудита 2013/2014 учебный год Дисциплина Литература Кол-во студентов Основная литература Анализ 28 30 1 финансовой *Анализ финансовой отчетности: учебник/под ред. М.А. Вахрушиной. – М.: отчетности 5д, 4з БУ 20 Вузовский учебник, 2008 *Донцова Л.В. Анализ финансовой отчетности: учеб. пособие / Л. В. 10 Донцова, Н. А. Никифорова. - М.: Изд-во Дело и Сервис, 2003. Илышева, Н. Н. Анализ финансовой отчетности [Электронный ресурс] : учеб....»

«Серия Среднее профессиональное образование Л.А. Введенская, М.Н. Черкасова Русской язык и купьтура речи Допущено Министерством образования Российской Федерации в качестве учебного пособия для студентов средних специальных заведений Издание 3-е Ростов-на-Дону Феникс 2004 ББК 81.2Р В24 Рецензенты: доктор филологических наук, профессор ЕЛ. Покровская кандидат педагогических наук, доцент Л.В. Голуб Введенская Л.А., Черкасова М.Н. В 24 Русский язык и культура речи. Серия Учебники, учебные пособия. —...»

«АНО ВПО ЦС РФ РОССИЙСКИЙ УНИВЕРСИТЕТ КООПЕРАЦИИ КАФЕДРА ТОВАРОВЕДЕНИЯ, ТОВАРНОГО КОНСАЛТИНГА И АУДИТА МЕТОДИЧЕСКИЕ РЕКОМЕНДАЦИИ ПО ВЫПОЛНЕНИЮ ВЫПУСКНОЙ КВАЛИФИКАЦИОННОЙ РАБОТЫ (РАЗДЕЛ: ПРОДОВОЛЬСТВЕННЫЕ ТОВАРЫ) специальность 080401.65 Товароведение и экспертиза товаров (по областям применения) Москва 2010 УДК 641.1 ББК 36-9 К 82 Криштафович В.И. Методические рекомендации по выполнению выпускной квалификационной работы (Раздел: продовольственные товары). - М.: Российский университет кооперации,...»

«МИНИСТЕРСТВО ОБРАЗОВАНИЯ И НАУКИ РОССИЙСКОЙ ФЕДЕРАЦИИ федеральное государственное бюджетное образовательное учреждение высшего профессионального образования НАЦИОНАЛЬНЫЙ МИНЕРАЛЬНО-СЫРЬЕВОЙ УНИВЕРСИТЕТ ГОРНЫЙ УТВЕРЖДАЮ Проректор по научной работе профессор В.Л. ТРУШКО ПРОГРАММА ВСТУПИТЕЛЬНОГО ИСПЫТАНИЯ ПО СПЕЦИАЛЬНОЙ ДИСЦИПЛИНЕ ГЕОМЕХАНИКА, РАЗРУШЕНИЕ ГОРНЫХ ПОРОД, РУДНИЧНАЯ АЭРОГАЗОДИНАМИКА И ГОРНАЯ ТЕПЛОФИЗИКА, соответствующей направленности (профилю) направления подготовки...»

«ЮРИДИЧЕСКАЯ И ЭКСПЕРТНАЯ ОЦЕНКА МЕДИЦИНСКИХ ОШИБОК, СВЯЗАННЫХ С ОБРАЩЕНИЕМ ЛЕКАРСТВ учебное пособие В.И. Витер А.Р.Поздеев А.Н. Яворский МИНИСТЕРСТВО ВНУТРЕННИХ ДЕЛ РОССИЙСКОЙ ФЕДЕРАЦИИ ФЕДЕРАЛЬНОЕ ГОСУДАРСТВЕННОЕ ОБРАЗОВАТЕЛЬНОЕ УЧРЕЖДЕНИЕ ВЫСШЕГО ПРОФЕССИОНАЛЬНОГО ОБРАЗОВАНИЯ НИЖЕГОРОДСКАЯ АКАДЕМИЯ МВД РОССИЙСКОЙ ФЕДЕРАЦИИ ИЖЕВСКИЙ ФИЛИАЛ В.И.ВИТЕР, А.Р.ПОЗДЕЕВ, А.Н.ЯВОРСКИЙ ЮРИДИЧЕСКАЯ И ЭКСПЕРТНАЯ ОЦЕНКА МЕДИЦИНСКИХ ОШИБОК, СВЯЗАННЫХ С ОБРАЩЕНИЕМ...»

«Фактическая обеспеченность учебной литературой на 2014-2015 учебный год по программе Перспектива 1 -4 классы (ФГОС) Всего Всего Предмет Клас Название учебной программы Вид Кем УМК - Учебники и Методические пособия учеб ШБ методич с программы утверждена рабочие тетради еских пособий Климанова Л.Ф., Бабушкина Т.В. Базовая МО и НРФ Климанова Л.Ф., Макеева Климанова Л.Ф., Макеева Русский 1 52 Русский язык. Рабочие программы. С.Г. Русский язык. Учебник С.Г. Русский язык язык Предметная линия...»

«2 КРЕАТИВНЫЕ РЕШЕНИЯ. В.В. Высоков КРЕАТИВНЫЕ МЕТОДЫ АНАЛИЗА И ГЕНЕРАЦИИ РЕШЕНИЙ Научно-практическое пособие Ростов-на-Дону 2014 3 УДК 658 В 93 Высоков В.В. Креативные методы анализа и генерации решений: Научно-практическое пособие. – Ростов н/Д: Издательскополиграфический комплекс РГЭУ (РИНХ), 2014. – 28 с. ISBN 978-5-7972-2025-1 В книге дается обзор методов и приемов, используемых для принятия креативных решений в практике работы банка Центр-инвест и его клиентов. Представлены методы анализа,...»

«Министерство образования и науки Государственное образовательное учреждение высшего профессионального образования Пермский государственный университет ЕСТЕСТВЕННОНАУЧНЫЙ ИНСТИТУТ Н.Г. Максимович, Е.А. Хайрулина ГЕОХИМИЧЕСКИЕ БАРЬЕРЫ И ОХРАНА ОКРУЖАЮЩЕЙ СРЕДЫ Учебное пособие Пермь 2011 УДК 504.06:550.4 ББК 20.18:26.30 M 18 Максимович, Н.Г. М18 Геохимические барьеры и охрана окружающей среды: учеб. пособие / Н.Г. Максимович, Е.А. Хайрулина; Перм. гос. ун-т. – Пермь, 2011. – 248с.: ил. ISBN...»

«ФЕДЕРАЛЬНОЕ АГЕНТСТВО ПО ОБРАЗОВАНИЮ УХТИНСКИЙ ГОСУДАРСТВЕННЫЙ ТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ Т.И. Шемиченко, А.А. Тюрина СОВРЕМЕННЫЙ РУССКИЙ ЯЗЫК Учебное пособие УХТА 2006 УДК 808.2я7 Ш 46 Шемиченко, Т.И. Современный русский язык [Текст]: учеб. пособие / Т.И. Шемиченко, А.А. Тюрина. – Ухта: УГТУ, 2006. – 104 с. ISBN 5-88179-420-6 В учебном пособии рассмотрена система основных норм современного русского языка. Наряду с теоретическими положениями, изложенными в кратком и доступном виде, предложены...»






 
2014 www.av.disus.ru - «Бесплатная электронная библиотека - Авторефераты, Диссертации, Монографии, Программы»

Материалы этого сайта размещены для ознакомления, все права принадлежат их авторам.
Если Вы не согласны с тем, что Ваш материал размещён на этом сайте, пожалуйста, напишите нам, мы в течении 1-2 рабочих дней удалим его.