Р.У. Себеста - Основные копцепции языков программирования (2001) (1160794), страница 88
Текст из файла (страница 88)
Керниган и Рнтчи (Кегп!8йап апд 1<!гоп!е (1978)) назвали оператор 8озо бесконечно неправильным, однако, несмотря на это, он был включен в язык С, разработанный Ритчн. В языках. исключившнх оператор 8о1о из своего состава, предусмотрены дополнительные управляющие операторы (обычно в виде цикла или выходов из подпрограмм) лля замены оператора 8о1о в стандартных случаях его применения. 7.5.2.
Вид)ья меток Одни языки, например А(.001 60 и С, используют дпя меток форму своих идентификаторов, другие (РОВТ)<АИ и Рапса!) — беззнаковые целые константы. Язык Ада использует форму своих идентификаторов в качестве цели для оператора 8о1о, но, когда метка ставится возле оператора, она должна отделяться символами «00Т». Рассмотрим следующий фрагмент программы; 9ого Г1И1ЯНЕ0/ «Г1Н1ВНЕ0» ЯНМ : ЯНМ + НЕХтз Угловые скобки облегчают поиск метки при чтении программы. В большинстве других языков метки приписываются к оператору с помощью двоеточия, как в следующем примере: 11паа!зев: аша:= вша + пенс; При разработке меток в языке Р1./1 вновь была выбрана конструкция. обладающая предельной гибкостью и сложностью.
Вместо использования меток в качестве простых констант язык РБ/1 позволяет меткам быть переменными. В этом виде им можно присваивать значения и использовать в качестве параметров подпрограмм. Это позволяет оператору 8озо действительно передавать управление в любую точку программы, причем эта цель не может определяться статически. Несмотря на то что эта гибкость иногда бывает полезна, такое использование меток наносит слишком большой вред читабельности программ, который невозможно оправдать. Вообразите, что вы пытаетесь прочитать и понять программу с переходами, цели которых зависят от значений, присвоенных во время выполнения программы.
Рассмотрите подпрограмму, имеющую несколько меток и оператор 8о1о, цель которого является формальным параметром. Чтобы определить цель этого оператора 8о1о, необхолимо знать вызывающий программный модуль и фактиче- 332 Глава 7. Структуры управления на уровне операторов ;кое значение параметра, используемого при вызове. Реализация переменных ссылок -экже сложна, а первую очередь из-за всевозможных способов, которыми переменные четки связываются со своими значениями. 7.5.3. Ограничвния пврвходов Вследствие сложности проблем, присущих операторам кого, большинство языков оггзничивает их использование.
Для того чтобы показать, как можно ограничить безуслов-ый переход, рассмотрим язык Рааса!. Метки в языке Рааса! должны объявляться так, как . гдто они являются переменными, но их нельзя передавать в качестве параметров, хра-лть в памяти или изменять. Область видимости метки такая же, как и у переменных, рядам с которыми она объявлена. В качестве части оператора досо метки должны быть зросто константами, а не выражениями или переменными со значениями в виде меток.
Пусть группа операторов представляет собой либо составной оператор, в том числе и -юную подпрограмму, либо набор операторов в цикле керееш Группа операторов яв-=.ется активной, если она начала, но не закончила свое выполнение. Ограничения языка . эзса! устанавливают, что целью оператора досо не может быть оператор внутри груп-ы операторов, не являющейся активной.
Следовательно, цель никогда не может при-эдэежать группе операторов, находящейся на том же уровне и вложенной более глубо° а. чем оператор доко. Это предотвращает наличие нескольких входов у управляющих ру ктур. Важная проблема, связанная с ограничениями языка Рааса), состоит в том, что воз. ажен переход во внешнюю подпрограмму.
Поскольку подпрограмма, в которую осуше.гвляется переход, является внешней, она должна быть активной. Рассмотрим следуюий пример: ркооес)оке виЬ1; 1аЬе1 100; ркоое6ике вцЬ2; досо 100; ети$1 )аиЬ2) 00: епйг )вцЬ1) 'эератор доко в этом примере является допустимым. Он передает управление в роди-ельскую подпрограмму аиЬ1, прерывая выполнение подпрограммы виЬ2, в которой -зходится оператор досо. Таким образом, оператор доьо может прерывать выполнение : зной или нескольких процедур, но не может инициировать их выполнение путем переоэа внутрь одной из них. Конечно, переход к оператору, являющемуся вызовом некото-.' й процедуры, неявно приводит к началу выполнения этой процедуры. Переход из одной процедуры в другую крайне вреден для читабельности программы .
следовательно, нежелателен. Поскольку в языке Рааса! цели операторов досо ограни.ены внешними ~руппами операторов, за исключением подпрограмм, можно предполо-: ить. что это сделано для повышения безопасности программ. ЗЗЗ 7.5. Безусловный переход Положительным результатом таких ограничений в языке Рааса[ является возможность перехола из процедуры к ее родительской процедуре или другому предлу.
Это позволяет передавать ошибочные условия в родительские процедуры для исправления. Этот процесс, однако, лучше реализуется с помощью механизма обработки исключительных ситуаций, разработанного в этом языке. Обработка исключительных ситуаций будет обсуждаться в главе 13. Все операторы выхода из циклов, рассмотренные в разделе 7.4.3, в действительности являются замаскированными операторами його. Однако они представляют собой значительно ограниченные операторы безусловного перехола и не ухудшают читабельность программ, поскольку их отсутствие сделало бы код неестественным, и понять его было бы гораздо труднее. 7.6. Защищенные команды Альтернативные и различные формы операторов ветвления и циклических структур были предложены Дийкстрой (О!)[гзгга (1975)).
Он стремился создать управляющие структуры, которые позволяли бы создавать правильные программы и не требовали бы их верификации или тестирования. Эта методология описана в работе [31)]сапа (197б). Защищенные команды рассматриваются в этой главе, потому что они являются основой двух лингвистических механизмов, разработанных позднее для параллельного программирования в двух языках — ОБР (Ноаге, 1978) и Ада. Параллельность в языке Ада обсуждается в главе 12.
Конструкция ветвления, предложенная Дийкстрой, имеет следующий вид: зй <булевское выражение> -> оператор [] <булевское выражение> -> оператор [] [) <булевское выражение»- оператор й. Замыкающее зарезервированное слово хд представляет собой открывающее зарезервированное слово, записанное наоборот. Эта форма замыкающего зарезервированного слова была взята из языка А[.ОО[, б8. Маленькие блоки, названные барьерами, используются для того, чтобы отделить защищенные операторы и использовать последовательность операторов. Эта конструкция ветвления похожа на многовариантное ветвление, но с другой семантикой. Все булевские выражения вычисляются каждый раз при достижении этой конструкции в программе. Если истинными являются несколько выражений, то для выполнения случайным образом выбирается один из соответствующих операторов. Если ни одно выражение не является истинным, возникает ошибка времени выполнения программы, приводящая к прекращению ее выполнения.
Это вынуждает программиста рассматривать и перечислять все возможности, как это делается в операторе баев языка Ада. Рассмотрим следующий пример: дй з = 0 -> апв := аив + [] 1 > 3 -> впп := аоп [) 3 > д -> аит := апп + з. хд Глава 7. Структуры управления на уровне операторов :-';ли ' = О и 3 > 1, то эта конструкция случайным образом выбирает первый нли тре-ий операторы присваивания. Если 1 = 3 и 1 е О, то возникает ошибка времени вы— лнения программы, поскольку нет ни одного истинного условия.
С помошью этой конструкции программист может использовать произвольный поря=:к выполнения операторов. Например. чтобы найти наибольшее из двух чисел, можно .; пользовать следующий оператор: ьй х >= у -> вах := х у >= х -> вах := у х'з .. езставленный фрагмент программы вычисляет требуемый результат, не переопреде-~я решения.
В частности, если х = у, то не имеет значения, что именно присваивается -еременной вах. Этот внд абстракции обеспечивается недетерминированной семанти. й такого оператора. Кроме того, конструкцию ветвления Дийкстры полезно использовать в программе, ".служиваюшей прерывания, которые имеют одинаковый приоритет. Семантику зашишенных команд трудно описать точно. В отличие от разработки про. змм. при описании семантики блок-схемы могут оказаться полезными.
На рис. 7.1 по° нана блок-схема, описываюшая подход, который использует оператор ветвления Днйк:-ры. Эта блок-схема относительно неточная, что отражает трудности в понимании сезнтики зашишенных команд. Структура цикла, предложенная Дийкстрой, имеет следующий вид: <!о <булевское выражение» - <оператор> <булевское выражение> -> <оператор> Семантика этой конструкции заключается в том, что все булевские выражения вы-исляются при каждом повторении цикла. Если истинными оказываются несколько вы:з;сепий, то олин из связанных с ними операторов выбирается лля выполнения случай-ь ч образом, после чего все выражения снова вычисляются. Когда все выражения одноэ "сменно станут ложными, цикл завершается. Рассмотрим следуюший фрагмент программы, приведенный в слегка измененном ви=" в работе !3!!!гзгга (!975).
Значения четырех переменных 71, с!2, с!3 и с!4 должны быть зорязочены так, чтобы выполнялосьусловне г!1 < с!2 < г!3 < с!4. с!о <!1 > <!2 -> севр:= г!14 г!1:= с!2г с!2:= Севрз с!2 > <!3 -> Севр:= г!24 с!2:= с!Зг с!3 ."= севрг г!3 > с!4 -> севр:= <!3! с!3:= <!4; с!4:= севрг ой Блок-схема, описывающая подход, используемый оператором цикла Дийкстры, показзна на рис. 7.2. Снова отметим, что семантика потока управления в этой конструкции не ь ожет быть изображена на блок-схеме точно.
7.6. Защищенные команды Рис. 7.1. Бяок-схеиа, описыеаюи~ая подход, испотьэуюисийся опери- тором еетпенияДийкстры 336 Глава 7. Структуры управления на уровне операторов Описанные выше конструкции называются "защищенными командами Дийкстры". Частично, интерес к ним объясняется тем, что они иллюстрируют, каким образом синтаксис и семантика операторов могут влиять на верификацию программ, и наоборот. Верификация программ действительно невозможна, если используются операторы безусловного перехода.