Главная · Поиск книг · Поступления книг · Top 40 · Форумы · Ссылки · Читатели

Настройка текста
Перенос строк


    Прохождения игр    
Demon's Souls |#13| Storm King
Demon's Souls |#12| Old Monk & Old Hero
Demon's Souls |#11| Мaneater part 2
Demon's Souls |#10| Мaneater (part 1)

Другие игры...


liveinternet.ru: показано число просмотров за 24 часа, посетителей за 24 часа и за сегодня
Rambler's Top100
Образование - Керниган, Ричи Весь текст 454.51 Kb

Язык Си

Предыдущая страница Следующая страница
1 ... 18 19 20 21 22 23 24  25 26 27 28 29 30 31 ... 39
ширину поля в битах. Поля описаны как UNSIGNED, чтобы под-
черкнуть, что они действительно будут величинами без знака.
    На отдельные поля можно ссылаться, как FLAGS.IS_STATIE,
FLAGS. IS_EXTERN, FLAGS.IS_KEYWORD И т.д., то есть точно так
же, как на другие члены структуры. Поля ведут себя подобно
небольшим целым без знака и могут участвовать в арифметичес-
ких выражениях точно так же, как и другие целые. Таким обра-
зом, предыдущие примеры более естественно переписать так:

    FLAGS.IS_EXTERN = FLAGS.IS_STATIC = 1;

для включения битов;

    FLAGS.IS_EXTERN = FLAGS.IS_STATIC = 0;

для выключения битов;

  IF (FLAGS.IS_EXTERN == 0 &&FLAGS.IS_STATIC == 0)...

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

    При работе с полями имеется ряд моментов, на которые
следует обратить внимание. По-видимому наиболее существенным
является то, что отражая природу различных аппаратных сред-
ств, распределение полей на некоторых машинах осуществляется
слева направо, а на некоторых справа налево. Это означает,
что хотя поля очень полезны для работы с внутренне опреде-
ленными структурами данных, при разделении внешне определяе-
мых данных следует тщательно рассматривать вопрос о том, ка-
кой конец поступает первым.
    Другие ограничения, которые следует иметь в виду: поля
не имеют знака; они могут храниться только в переменных типа
INT (или, что эквивалентно, типа UNSIGNED); они не являются
массивами; они не имеют адресов, так что к ним не применима
операция &.

     6.8. Объединения

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

  UNION U_TAG \(
  INT IVAL;
  FLOAT FVAL;
  CHAR *PVAL;
  \) UVAL;

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

    Синтаксически доступ к членам объединения осуществляется
следующим образом:

  имя объединения.член
  --------------------
или
  указатель объединения ->член
  ----------------------------

то есть точно так же, как и в случае структур. если для отс-
леживания типа, хранимого в данный момент в UVAL, использу-
ется переменная UTYPE, то можно встретить такой участок
программы:

  IF (UTYPE == INT)
  PRINTF("%D\N", UVAL.IVAL);
  ELSE IF (UTYPE == FLOAT)
  PRINTF("%F\N", UVAL.FVAL);
  ELSE IF (UTYPE == STRING)
  PRINTF("%S\N", UVAL.PVAL);
  ELSE
  PRINTF("BAD TYPE %D IN UTYPE\N", UTYPE);

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

 STRUCT \(
 CHAR *NAME;
 INT FLAGS;
 INT UTYPE;
 UNION \(
 INT IVAL;
 FLOAT FVAL;
 CHAR *PVAL;
 \) UVAL;
  \) SYMTAB[NSYM];

на переменную IVAL можно сослаться как

  SYMTAB[I].UVAL.IVAL

а на первый символ строки PVAL как

  *SYMTAB[I].UVAL.PVAL

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

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

     6.9. Определение типа

   В языке "C" предусмотрена возможность, называемая TYPEDEF
для введения новых имен для типов данных. Например, описание

TYPEDEF INT LENGTH;

делает имя LENGTH синонимом для INT. "Тип" LENGTH может быть
использован в описаниях, переводов типов и т.д. Точно таким
же образом, как и тип INT:

   LENGTH   LEN, MAXLEN;
   LENGTH   *LENGTHS[];

Аналогично описанию

    TYPEDEF CHAR *STRING;

делает STRING синонимом для CHAR*, то есть для указателя на
символы, что затем можно использовать в описаниях вида

    STRING P, LINEPTR[LINES], ALLOC();

    Обратите внимание, что объявляемый в конструкции TYPEDEF
тип появляется в позиции имени переменной, а не сразу за
словом TYPEDEF. Синтаксически конструкция TYPEDEF подобна
описаниям класса памяти EXTERN, STATIC и т. Д. мы также ис-
пользовали прописные буквы, чтобы яснее выделить имена.
    В качестве более сложного примера мы используем конст-
рукцию TYPEDEF для описания узлов дерева, рассмотренных ра-
нее в этой главе:

 TYPEDEF STRUCT TNODE \(     /* THE BASIC NODE */
 CHAR *WORD; /* POINTS TO THE TEXT */
 INT COUNT; /* NUMBER OF OCCURRENCES */
 STRUCT TNODE *LEFT;     /* LEFT CHILD */
 STRUCT TNODE *RIGHT;    /* RIGHT CHILD */
 \) TREENODE, *TREEPTR;

В результате получаем два новых ключевых слова: TREENODE
(структура) и TREEPTR (указатель на структуру). Тогда функ-
цию TALLOC можно записать в виде

 TREEPTR TALLOC()
 \(
    CHAR *ALLOC();
    RETURN((TREEPTR) ALLOC(SIZEOF(TREENODE)));
 \)

    Необходимо подчеркнуть, что описание TYPEDEF не приводит
к созданию нового в каком-либо смысле типа; оно только до-
бавляет новое имя для некоторого существующего типа. при
этом не возникает и никакой новой семантики: описанные таким
способом переменные обладают точно теми же свойствами, что и
переменные, описанные явным образом. По существу конструкция
TYPEDEF сходна с #DEFINE за исключением того, что она интер-
претируется компилятором и потому может осуществлять подста-
новки текста, которые выходят за пределы возможностей мак-
ропроцессора языка "C". Например,

 TYPEDEF INT (*PFI) ();

создает тип PFI для "указателя функции, возвращающей значе-
ние типа INT", который затем можно было бы использовать в
программе сортировки из главы 5 в контексте вида

PFI STRCMP, NUMCMP, SWAP;

    Имеются две основные причины применения описаний
TYPEDEF. Первая причина связана с параметризацией программы,
чтобы облегчить решение проблемы переносимости. Если для ти-
пов данных, которые могут быть машинно-зависимыми, использо-
вать описание TYPEDEF, то при переносе программы на другую
машину придется изменить только эти описания. Одна из типич-
ных ситуаций состоит в использовании определяемых с помощью
TYPEDEF имен для различных целых величин и в последующем
подходящем выборе типов SHORT, INT и LONG для каждой имею-
щейся машины.
Второе назначение TYPEDEF состоит в обеспечении лучшей доку-
ментации для программы - тип с именем TREEPTR может оказать-
ся более удобным для восприятия, чем тип, который описан
только как указатель сложной структуры.
И наконец, всегда существует вероятность, что в будущем ком-
пилятор или некоторая другая программа, такая как LINT, смо-
жет использовать содержащуюся в описаниях TYPEDEF информацию
для проведения некоторой дополнительной проверки программы.

      * 7. Ввод и вывод *

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

     7.1. Обращение к стандартной библиотеке

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

 #INCLUDE

в файле STDIO.H определяются некоторые макросы и переменные,
используемые библиотекой ввода/вывода. Использование угловых
скобок вместо обычных двойных кавычек - указание компилятору
искать этот файл в справочнике, содержащем заголовки стан-
дартной информации (на системе UNIX обычно LUSRLINELUDE).
    Кроме того, при загрузке программы может оказаться необ-
ходимым указать библиотеку явно; на системе PDP-11 UNIX,
например, команда компиляции программы имела бы вид:

CC   исходные файлы и т.д. -LS

где -LS указывает на загрузку из стандартной библиотеки.

     7.2. Стандартный ввод и вывод - функции GETCHAR и PUTCHAR

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

вводимый символ. В большинстве сред, которые поддерживают
язык "с", терминал может быть заменен некоторым файлом с по-
мощью обозначения < : если некоторая программа PROG исполь-
зует функцию GETCHAR то командная строка

PROG : если PROG использует PUTCHAR,
то командная строка

PROG>OUTFILE

приведет к записи стандартного вывода в файл OUTFILE, а не
на терминал. На системе UNIX можно также использовать поточ-
ный механизм. Строка

 PROG \! ANOTHERPROG

помещает стандартный вывод PROG в стандартный ввод
ANOTHERPROG. И опять PROG не будет осведомлена об изменении
Предыдущая страница Следующая страница
1 ... 18 19 20 21 22 23 24  25 26 27 28 29 30 31 ... 39
Ваша оценка:
Комментарий:
  Подпись:
(Чтобы комментарии всегда подписывались Вашим именем, можете зарегистрироваться в Клубе читателей)
  Сайт:
 
Комментарии (1)

Реклама