Объединения

Язык С
Учебное введение Оператор FOR Копирование файла Подсчет строк Массивы Аргументы - вызов по значению Область действия: внешние переменные Резюме Константы Арифметические операции Затем, если один из операндов имеет тип DOUBLE, то другой преобразуется в DOUBLE, и результат имеет тип DOUBLE Побитовые логические операции Условные выражения Поток управления Переключатель Цикл DO - WHILE Оператор GOTO и метки Функции, возвращающие нецелые значения Внешние переменные Правила, определяющие область действия Статические переменные Инициализация Препроцессор языка “C” Указатели и адреса Адресная арифметика Указатели символов и функции Многомерные массивы Инициализация массивов указателей Структуры Массивы сруктур Указатели на структуры Поиск в таблице Объединения Ввод и вывод Средства ввода/вывода не являются составной частью языка “с”, так что мы не выделяли их в нашем предыдущем изложении Форматный вывод - функция PRINTF Обычные символы (не %), которые предполагаются совпадающими со следующими отличными от символов пустых промежутков символами входного потока Форматное преобразование в памяти Низкоуровневый ввод/вывод - операторы READ и WRITE Произвольный доступ - SEEK и LSEEK Пример - распределитель памяти Лексические соглашения Имеется шесть классов лексем: идентификаторы, ключевые слова, константы, строки, операции и другие разделители Характеристики аппаратных средств Следующая ниже таблица суммирует некоторые свойства аппаратного оборудования, которые меняются от машины к машине Первичные выражения Первичные выражения, включающие ., ->, индексацию и обращения к функциям, группируются слева направо Унарные операции Выражение с унарными операциями группируется справо налево Операции равенства Выражение-равенства: выражение == выражение выражение != выражение Операция запятая Выражение-с-запятой: выражение , выражение Внешние определения данных Снова о типах В этом разделе обобщаются сведения об операциях, которые можно применять только к объектам определенных типов Анахронизмы Так как язык “C” является развивающимся языком, в старых программах можно встретить некоторые устаревшие конструкции
424070
знаков
0
таблиц
0
изображений

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

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

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

UNION U_TAG ( INT IVAL;

FLOAT FVAL;

CHAR *PVAL;

) UVAL;

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

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

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

IF (UTYPE == INT) PRINTF(“%DN”, UVAL.IVAL);

ELSE IF (UTYPE == FLOAT) PRINTF(“%FN”, UVAL.FVAL);

ELSE IF (UTYPE == STRING) PRINTF(“%SN”, UVAL.PVAL);

ELSE PRINTF(“BAD TYPE %D IN UTYPEN”, 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 информацию для проведения некоторой дополнительной проверки программы.

152


Информация о работе «Язык С»
Раздел: Информатика, программирование
Количество знаков с пробелами: 424070
Количество таблиц: 0
Количество изображений: 0

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

Скачать
48443
0
0

... основаниям. При этом философская абстракция языка оказывается неразрывно связана с основными темами и движениями философии в целом. Более конкретно, на ранние стадии традиционно рассматриваемого в рамках АФ анализа обыденного языка глубокое влияние оказала философия Дж. Э. Мура, особенно его учение о здравом смысле, согласно которому такие понятия, как «человек», «мир», «я», «внешний мир», « ...

Скачать
43709
0
0

... и других странах СНГ, а также облегчение доступа к русской и мировой культуре и науке. Таким образом, судя по данным наших исследований, востребованность русского языка осталась в республике достаточно высокой. Многие представители современной молдавской молодежи продолжают, как их отцы и деды, тянуться к русской культуре, научным и техническим достижениям России. Русский язык остается языком ...

Скачать
39778
0
1

... рисуночное словесно-слоговое письмо). Памятники среднеэламского периода (14—12 вв. до н.э.) выполнены аккадской клинописью. Памятники новоэламского периода относятся к 8—6 вв. до н.э. Был официальным языком в персидском государстве Ахеменидов в 6—4 вв. предполагается, что он, подвергшись влиянию древнеперсидского, сохранился до раннего средневековья. 7. Бурушаски язык Язык бурушаски ( ...

Скачать
64931
0
0

... /диалект), скифский, согдийский, среднеперсидский, таджикский, таджриши (язык/диалект), талышский, татский, хорезмийский, хотаносакский, шугнано-рушанская группа языков, ягнобский, язгулямский и др. Они относятся к индоиранской ветви индоевропейских языков. Области распространения: Иран, Афганистан, Таджикистан, некоторые районы Ирака, Турции, Пакистана, Индии, Грузии, Российской Федерации. Общее ...

0 комментариев


Наверх