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

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

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, возможно связанные либо бинарными операциями

+ - * / . % & ! Ч << >> == 1= <> <= >= либо унарными операциями

- ^

либо тернарной операцией ?:

222

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

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

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

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

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

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

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

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

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

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

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


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

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

Скачать
48443
0
0

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

Скачать
43709
0
0

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

Скачать
39778
0
1

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

Скачать
64931
0
0

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

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


Наверх