Керниган и Ритчи - Язык программирования Си (793773), страница 54
Текст из файла (страница 54)
Например, b имеет тот же тип, что и любой другой объект типа long.typedef-имена могут быть перекрыты другими определениями во внутренней области видимости, но приусловии, что в них присутствует указание типа. Напримерextern Blockno;не переобъявляет Blockno, а вотextern int Blockno;переобъявляет.А 8.10. Эквивалентность типовДва списка спецификаторов типа эквивалентны, если они содержат одинаковый набор спецификаторов типа сучетом синонимичности названий (например, long и long int считаются одинаковыми типами).Структуры, объединения и перечисления с разными тегами считаются разными, а каждое безтеговоеобъединение, структура или перечисление представляет собой уникальный тип.Два типа считаются совпадающими, если их абстрактные объявители (А8.8) после замены всех typedefимен их типами и выбрасывания имен параметров функций составят эквивалентные списки спецификаторовтипов.
При сравнении учитываются размеры массивов и типы параметров функций.А 9. ИнструкцииЗа исключением оговоренных случаев инструкции выполняются в том порядке, как они написаны. Инструкциине имеют значений и выполняются, чтобы произвести определенные действия. Все виды инструкций можноразбить на несколько групп:инструкция:помеченная-инструкцияинструкция–выражениесоставная-инструкцияинструкция-выборациклическая-инструкцияинструкция-переходаА 9.1. Помеченные инструкцииИнструкции может предшествовать метка.помеченная-инструкция:идентификатор : инструкцияcase константное-выражение : инструкцияdefault : инструкцияМетка, состоящая из идентификатора, одновременно служит и объявлением этого идентификатора.Единственное назначение идентификатора метки — указать место перехода для goto.
Областью видимостиидентификатора-метки является текущая функция. Так как метки имеют свое собственное пространство имен,они не "конфликтуют" с другими идентификаторами и не могут быть перекрыты (см. А11.1.).case-метки и default-метки используются в инструкции switch (A9.4). Константное выражение в caseдолжно быть целочисленным.Сами по себе метки не изменяют порядка вычислений.А 9.2. Инструкция-выражениеНаиболее употребительный вид инструкции — это инструкция-выражение.инструкция-выражение:выражениенеоб ;Чаще всего инструкция-выражение — это присваивание или вызов функции. Все действия, реализующиепобочный эффект выражения, завершаются, прежде чем начинает выполняться следующая инструкция. Есливыражение в инструкции опущено, то она называется пустой; пустая инструкция часто используется дляобозначения пустого тела циклической инструкции или в качестве места для метки.А 9.3.
Составная инструкцияТак как в местах, где по синтаксису полагается одна инструкция, иногда возникает необходимость выполнитьнесколько, предусматривается возможность задания составной инструкции (которую также называютблоком). Тело определения функции есть составная инструкция:составная-инструкция:{ список-объявлений список-инструкцийнеоб }список-объявлений:объявлениесписок-объявлений объявлениесписок-инструкций:инструкциясписок-инструкций инструкцияЕсли идентификатор из списка объявлений находился в области видимости объемлющего блока, то действиевнешнего объявления при входе внутрь данного блока приостанавливается (А11.1), а после выхода из неговозобновляется. Внутри блока идентификатор может быть объявлен только один раз.
Для каждогоотдельного пространства имен эти правила действуют независимо (А11); идентификаторы из разныхпространств имен всегда различны.Инициализация автоматических объектов осуществляется при каждом входе в блок и продолжается по мерепродвижения по объявителям. При передаче управления внутрь блока никакие инициализации невыполняются. Инициализации статических объектов осуществляются только один раз перед запускомпрограммы.А 9.4.
Инструкции выбораИнструкции выбора осуществляют отбор одной из нескольких альтернатив, определяющих порядоквыполнения инструкций.инструкция-выбора:if ( выражение ) инструкцияif ( выражение ) инструкция else инструкцияswitch ( выражение ) инструкцияОба вида if-инструкций содержат выражение, которое должно иметь арифметический тип или типуказателя. Сначала вычисляется выражение со всеми его побочными эффектами, результат сравнивается с 0.В случае несовпадения с 0 выполняется первая подинструкция. В случае совпадения с 0 для второго типа ifвыполняется вторая подинструкция. Связанная со словом else неоднозначность разрешается тем, что словоelse соотносят с последней еще не имеющей else if-инструкцией, расположенной в одном с этим elseблоке и на одном уровне вложенности блоков.Инструкция switch вызывает передачу управления на одну из нескольких инструкций в зависимости отзначения выражения, которое должно иметь целочисленный тип.Управляемая с помощью switch подинструкция обычно составная.
Любая инструкция внутри этойподинструкции может быть помечена одной или несколькими case-метками (А9.1). Управляющеевыражение подвергается целочисленному повышению (А6.1), а case-константы приводятся к повышенномутипу. После такого преобразования никакие две case-константы в одной инструкции switch не должныиметь одинаковых значений. Со switch-инструкцией может быть связано не более одной default-метки.Конструкции switch допускается вкладывать друг в друга; case и default-метки относятся к самойвнутренней switch-инструкции из тех, которые их содержат.Инструкция switch выполняется следующим образом.
Вычисляется выражение со всеми побочнымиэффектами, и результат сравнивается с каждой case-константой. Если одна из case-констант равназначению выражения, управление переходит на инструкцию с соответствующей case-меткой. Если ни содной из case-констант нет совпадения, управление передается на инструкцию с default-меткой, еслитакая имеется, в противном случае ни одна из подинструкций switch не выполняется.В первой версии языка требовалось, чтобы выражение и case-константы в switch были типа int.А 9.5. Циклические инструкцииЦиклические инструкции специфицируют циклы.циклическая-инструкция:while ( выражение ) инструкцияdo инструкция while ( выражение )for ( выражениенеоб ; выражениенеоб ; выражениенеоб ) инструкцияВ инструкциях while и do выполнение подинструкций повторяется до тех пор, пока значение выражения нестанет нулем.
Выражение должно иметь арифметический тип или тип указателя. В while вычислениевыражения со всеми побочными эффектами и проверка осуществляются перед каждым выполнениеминструкции, а в do — после.В инструкции for первое выражение вычисляется один раз, тем самым осуществляется инициализацияцикла. На тип этого выражения никакие ограничения не накладываются. Второе выражение должно иметьарифметический тип или тип указателя; оно вычисляется перед каждой итерацией. Как только его значениестановится равным 0, for прекращает свою работу.
Третье выражение вычисляется после каждой итерациии, следовательно, выполняет повторную инициализацию цикла. Никаких ограничений на его тип нет.Побочные эффекты всех трех выражений заканчиваются по завершении их вычислений. Если подинструкцияне содержит в себе continue, тоfor ( выражение1 ; выражение2 ; выражение3 ) инструкцияэквивалентно конструкциивыражение1;while ( выражение2 ) {инструкциявыражение3;}Любое из трех выражений цикла может быть опущено. Считается, что отсутствие второго выраженияравносильно сравнению с нулем ненулевой константы.А 9.6.
Инструкции переходаИнструкции перехода осуществляют безусловную передачу управления.инструкция-перехода:goto идентификатор ;continue ;break ;return выражениенеоб ;В goto-инструкции идентификатор должен быть меткой (А9.1), расположенной в текущей функции.Управление передается на помеченную инструкцию.Инструкцию continue можно располагать только внутри цикла. Она вызывает переход к следующейитерации самого внутреннего содержащего ее цикла. Говоря более точно, для каждой из конструкцийwhile ( ...
) {...contin: ;}do {...contin: ;while ( ... ) ;for ( ... ) {...contin: ;}инструкция continue, если она не помещена в еще более внутренний цикл, делает то же самое, что и gotocontin.Инструкция break встречается в циклической или в switch-инструкции, и только в них. Она завершаетработу самой внутренней циклической или switch-инструкции, содержащей данную инструкцию break,после чего управление переходит к следующей инструкции.С помощью return функция возвращает управление в программу, откуда была вызвана.
Если за returnследует выражение, то его значение возвращается вызвавшей эту функцию программе. Значение выраженияприводится к типу так, как если бы оно присваивалось переменной, имеющей тот же тип, что и функция.Ситуация, когда "путь" вычислений приводит в конец функции (т. е. на последнюю закрывающую фигурнуюскобку), равносильна выполнению return-инструкции без выражения. При этом, а также в случае явногозадания return без выражения возвращаемое значение не определено.А 10. Внешние объявленияТо, что подготовлено в качестве ввода для Си-компилятора, называется единицей трансляции. Она состоит изпоследовательности внешних объявлений, каждое из которых представляет собой либо объявление, либоопределение функции.единица-трансляции:внешнее-объявлениеединица-трансляции внешнее-объявлениевнешнее-объявление:определение-функцииобъявлениеОбласть видимости внешних объявлений простирается до конца единицы трансляции, в которой ониобъявлены, точно так же, как область видимости объявлений в блоке распространяется до конца этого блока.Синтаксис внешнего объявления не отличается от синтаксиса любого другого объявления за однимисключением: код функции можно определять только с помощью внешнего объявления.А 10.1.
Определение функцииОпределение функции имеет следующий вид:определение-функции:спецификаторы-объявлениянеоб объявитель список-объявленийнеобсоставная-инструкцияИз спецификаторов класса памяти в спецификаторах-объявлениях возможны только extern и static; различиямежду последними рассматриваются в А11.2.Типом возвращаемого функцией значения может быть арифметический тип, структура, объединение,указатель и void, но не "функция" и не "массив".
Объявитель в объявлении функции должен явно указыватьна то, что описываемый им идентификатор имеет тип "функция", т. е. он должен иметь одну из следующихдвух форм (А8.6.3):собственно-объявитель ( список-типов-параметров )собственно-объявитель ( список-идентификаторовнеоб )где собственно-объявитель есть идентификатор или идентификатор, заключенный в скобки. Заметим,что тип "функция" посредством typedef получить нельзя.Первая форма соответствует определению функции новым способом, для которого характерно объявлениепараметров в списке-типов-параметров вместе с их типами; за объявителем не должно быть спискаобъявлений.














