обеих операций проводятся обычные арифметические преобразо-
вания их операндов, каждый из которых должен быть целочис-
ленного типа. Затем правый операнд преобразуется к типу INT;
результат имеет тип левого операнда. Результат не определен,
если правый операнд отрицателен или больше или равен, чем
длина объекта в битах.
Выражение-сдвига:
выражение << выражение
выражение >> выражение
Значением выражения E1<>E2 яв-
ляется E1, сдвинутое вправо на E2 битовых позиций. Если E1
имеет тип UNSIGNE, то сдвиг вправо гарантированно будет ло-
гическим (заполнение нулем); в противном случае сдвиг может
быть (и так и есть на PDP-11) арифметическим (освобождающие-
ся биты заполняются копией знакового бита).
15.6. Операции отношения
Операции отношения группируются слева направо, но этот
факт не очень полезен; выражение A выражение
выражение <= выражение
выражение >= выражение
Операции < (меньше), > (больше), <= (меньше или равно) и >=
(больше или равно) все дают 0, если указанное отношение лож-
но, и 1, если оно истинно. Результат имеет тип ITN. Выполня-
ются обычные арифметические преобразования. Могут сравни-
ваться два указателя; результат зависит от относительного
расположения указываемых объектов в адресном пространстве.
Сравнение указателей переносимо только в том случае, если
указатели указывают на объекты из одного и того же массива.
15.7. Операции равенства
Выражение-равенства:
выражение == выражение
выражение != выражение
Операции == (равно) и != (не равно) в точности аналогичны
операциям отношения, за исключением того, что они имеют бо-
лее низкий уровень старшинства. (Поэтому значение выражения
A
15.8. Побитовая операция 'и'
Выражение-и:
выражение & выражение
Операция & является ассоциативной, и включающие & выражения
могут быть переупорядочены. Выполняются обычные арифметичес-
кие преобразования; результатом является побитовая функция
'и' операндов. Эта операция применима только к операндам це-
лочисленного типа.
15.9. Побитовая операция исключающего 'или'
Выражение-исключающего-или:
выражение ^ выражение
Операция ^ является ассоциативной, и включающие ^ выражения
могут быть переупорядочены. выполняются обычные арифметичес-
кие преобразования; результатом является побитовая функция
исключающего 'или' операндов. Операция применима только к
операндам целочисленного типа.
15.10. Побитовая операция включающего 'или'
Выражение-включающего-или:
выражение \! Выражение
Операция \! Является ассоциативной, и содержащие \! Выраже-
ния могут быть переупорядочены. выполняются обычные арифме-
тические преобразования; результатом является побитовая фун-
кция включающего 'или' операндов. Операция применима только
к операндам целочисленного типа.
15.11. Логическая операция 'и'
Выражение-логического-и:
выражение && выражение
Операция && группируется слева направо. Она возвращает 1,
если оба ее операнда отличны от нуля, и 0 в противном слу-
чае. В отличие от & операция && гарантирует вычисление слева
направо; более того, если первый операнд равен 0, то значе-
ние второго операнда вообще не вычисляется.
Операнды не обязаны быть одинакового типа, но каждый из
них должен быть либо одного из основных типов, либо указате-
лем. результат всегда имеет тип ITN.
15.12. Операция логического 'или'
Выражение-логического-или:
выражение \!\! выражение
Операция \!\! Группируется слева направо. Она возвращает 1,
если один из операндов отличен от нуля, и 0 в противном слу-
чае. В отличие от операции \! Операция \!\! Гарантирует вы-
числение слева направо; более того, если первый операнд от-
личен от нуля, то значение второго операнда вообще не вычис-
ляется.
Операнды не обязаны быть одинакового типа, но каждый из
них должен быть либо одного из основных типов, либо указате-
лем. Результат всегда имеет тип INT.
15.13. Условная операция
Условное-выражение:
выражение ? выражение : выражение
Условные выражения группируются слево направо. Вычисляется
значение первого выражения, и если оно отлично от нуля, то
результатом будет значение второго выражения; в противном
случае результатом будет значение третьего выражения. Если
это возможно, проводятся обычные арифметические преобразова-
ния, с тем, чтобы привести второе и третье выражения к обще-
му типу; в противном случае, если оба выражения являются
указателями одинакового типа, то результат имеет тот же тип;
в противном случае одно выражение должно быть указателем, а
другое - константой 0, и результат будет иметь тип указате-
ля. Вычисляется только одно из второго и третьего выражений.
15.14. Операция присваивания
Имеется ряд операций присваивания, каждая из которых
группируется слева направо. Все операции требуют в качестве
своего левого операнда L-значение, а типом выражения присва-
ивания является тип его левого операнда. Значением выражения
присваивания является значение, хранимое в левом операнде
после того, как присваивание уже будет произведено. Две час-
ти составной операции присваивания являются отдельными лек-
семами.
Выражение-присваивания:
L-значение = выражение
L-значение += выражение
L-значение -= выражение
L-значение *= выражение
L-значение /= выражение
L-значение %= выражение
L-значение >>= выражение
L-значение <<= выражение
L-значение &= выражение
L-значение ^= выражение
L-значение \!= выражение
Когда производится простое присваивание C'=', значение
выражения заменяет значение объекта, на которое ссылается
L-значение. Если оба операнда имеют арифметический тип, то
перед присваиванием правый операнд преобразуется к типу ле-
вого операнда.
О свойствах выражения вида E1 оп = E2, где Oп - одна из
перечисленных выше операций, можно сделать вывод, если
учесть, что оно эквивалентно выражению E1 = E1 оп (E2); од-
нако выражение E1 вычисляется только один раз. В случае опе-
раций += и -= левый операнд может быть указателем, причем
при этом (целочисленный) правый операнд преобразуется таким
образом, как объяснено в п. 15.4; все правые операнды и все
отличные от указателей левые операнды должны иметь арифмети-
ческий тип.
Используемые в настоящее время компиляторы допускают
присваивание указателя целому, целого указателю и указателя
указателю другого типа. такое присваивание является чистым
копированием без каких-либо преобразований. Такое употребле-
ние операций присваивания является непереносимым и может
приводить к указателям, которые при использовании вызывают
ошибки адресации. Тем не менее гарантируется, что присваива-
ние указателю константы 0 дает нулевой указатель, который
можно отличать от указателя на любой объект.
15.15. Операция запятая
Выражение-с-запятой:
выражение , выражение
Пара выражений, разделенных запятой, вычисляется слева нап-
раво и значение левого выражения отбрасывается. Типом и зна-
чением результата является тип и значение правого операнда.
Эта операция группируется слева направо. В контексте, где
запятая имеет специальное значение, как, например, в списке
фактических аргументов функций (п. 15.1) Или в списках ини-
циализаторов (п. 16.6), Операция запятая, описываемая в этом
разделе, может появляться только в круглых скобках; напри-
мер, функция
F(A,(T=3,T+2),C)
имеет три аргумента, второй из которых имеет значение 5.
16. Описания
Описания используются для указания интерпретации, кото-
рую язык "C" будет давать каждому идентификатору; они не
обязательно резервируют память, соответствующую идентифика-
тору. Описания имеют форму
Описание:
спецификаторы-описания список-описателей
необ;
Описатели в списке описателей содержат описываемые идентифи-
каторы. Спецификаторы описания представляют собой последова-
тельность спецификаторов типа и спецификаторов класса памя-
ти.
Спецификаторы-описания:
спецификатор-типа спецификаторы-описания
необ
спецификатор-класса-памяти спецификатор-описания
необ
список должен быть самосогласованным в смысле, описываемом
ниже.
16.1. Спецификаторы класса памяти
Ниже перечисляются спецификаторы класса памяти:
Спецификатор-класса-памяти:
AUTO
STATIC
EXTERN
REGISTER
TYPEDEF
Спецификатор TYPEDEF не реализует памяти и называется
"спецификатором класса памяти" только по синтаксическим со-
ображениям; это обсуждается в п. 16.8. Смысл различных клас-
сов памяти был обсужден в п. 12.
Описания AUTO, STATIC и REGISTER служат также в качестве
определений в том смысле, что они вызывают резервирование
нужного количества памяти. В случае EXTERN должно присутст-
вовать внешнее определение (п. 18) Указываемых идентификато-
ров где-то вне функции, в которой они описаны.
Описание REGISTER лучше всего представлять себе как опи-
сание AUTO вместе с намеком компилятору, что описанные таким
образом переменные будут часто использоваться. Эффективны
только несколько первых таких описаний. Кроме того, в регис-
трах могут храниться только переменные определенных типов;
на PDP-11 это INT, CHAR или указатель. Существует и другое
ограничение на использование регистровых переменных: к ним
нельзя применять операцию взятия адреса &. При разумном ис-
пользовании регистровых описаний можно ожидать получения
меньших по размеру и более быстрых программ, но улучшение в
будущем генерирования кодов может сделать их ненужными.
Описание может содержать не более одного спецификатора
класса памяти. Если описание не содержит спецификатора клас-
са памяти, то считается, что он имеет значение AUTO, если
описание находится внутри некоторой функции, и EXTERN в про-
тивном случае. исключение: функции никогда не бывает автома-
тическими.
16.2. Спецификаторы типа
Ниже перечисляются спецификаторы типа.
Спецификатор-типа:
CHAR
SHORT
INT
LONG
UNSIGNED
FLOAT
DOUBLE
спецификатор-структуры-или-объединения
определяющее-тип-имя
Слова LONG, SHORT и USIGNED можно рассматривать как при-
лагательные; допустимы следующие комбинации:
SHORT INT
LONG INT
USIGNED INT
LONG FLOAT
Последняя комбинация означает то же, что и DOUBLE. В осталь-
ном описание может содержать не более одного спецификатора
типа. Если описание не содержит спецификатора типа, то счи-
тается, что он имеет значение INT.
Спецификаторы структур и объединений обсуждаются в п.
16.5; Описания с определяющими тип именами TYPEDEF обсужда-
ются в п. 16.8.
16.3. Описатели
Входящий в описание список описателей представляет собой
последовательность разделенных запятыми описателей, каждый
из которых может иметь инициализатор.
Список-описателей:
инициализируемый-описатель
инициализируемый-описатель, список-описателей
инициализируемый-описатель:
описатель-инициализатор
необ
Инициализаторы описываются в п. 16.6. Спецификаторы и описа-
ния указывают тип и класс памяти объектов, на которые ссыла-
ются описатели. Описатели имеют следующий синтаксис:
описатель:
идентификатор
( описатель )
* описатель
описатель ()
описатель [константное-выражение
необ]
Группирование такое же как и в выражениях.
16.4. Смысл описателей
Каждый описатель рассматривается как утверждение того,
что когда конструкция той же самой формы, что и описатель,
появляется в выражении, то она выдает объект указанного типа
и указанного класса памяти. Каждый описатель содержит ровно
один идентификатор; это именно тот идентификатор, который и
описывается.
Если в качестве описателя появляется просто идентифика-
тор, то он имеет тип, указываемый в специфицирующем заголов-
ке описания.
Описатель в круглых скобках идентичен описателю без
круглых скобок, но круглые скобки могут изменять связи в
составных описателях. Примеры смотри ниже.
Представим себе описание