Р.У. Себеста - Основные копцепции языков программирования (2001) (1160794), страница 78
Текст из файла (страница 78)
В языке Рааса! булевские операторы имеют более высокий приоритет, чем операторы отношения, поэтому выражение а > 5 ог а < О в языке Разса! недопустимо (поскольку 5 не является допустимым булевским оператором). Правильным вариантом этого выражения будет следующий: (а > 5) ог (а < О) 6.6. Сокращенное вычисление Результат сокращенного вычисления выражения (з))оп-с(гсц(( еча)ца((оп) определяется без вычисления всех операндов и/или операторов. Например, если значение переменной А равно О, то значение арифметического выражения (13 * А) ~ (В / 13 - 1) не зависит от значения выражения (В / 13 - 1), поскольку для любого х * х = О.
Поэтому, если значение переменной А равно О, то вычислять значение выражения (В / 13 - 1) не требуется, как не требуется выполнять и второе умножение. Впрочем, во время выполнения программы такое сокращение вычислений обнаружить нелегко, поэтому оно никогда не используется. Если значение переменной А меньше нуля, то значение булевского выражения 291 6.6. Сокращенное вычисление (А >= О) а (В < 1О) не зависит от второго оператора отношения. поскольку для всех х значение выражения (РА' БЕ апс] х) равно РАЬЯЕ.
Поэтому, если А < О, то нам не требуется вычислять значение переменной В, сравнивать ее с константой 10 и выполнять логический оператор апа, причем (в отличие от арифметического выражения) это сокращение выражений легко обнаружить и использовать во время выполнения программы. Многие программисты в языке Рааса! сталкивались с проблемой при попытке записать цикл поиска в таблице с использованием оператора нвх1е.
Если предположить, что 11вь [1.. 11яг1ег] — это массив, в котором выполняется поиск, а йеу — искомая величина, можно создать такую программу поиска: 1гоех:- 1; нЫ1е (1пс(ех <= 11ас1еп) апо (11вг [1пс(ех] <> кеу) с(о 1пс(ех:= 1пс)ех + 1 Проблема состоит в том, что большинство стандартных реализаций языка Разов! не используют сокращенные вычисления, поэтому в булевском выражении оператора мЬ11е второе выражение отношения вычисляется независимо от результата первого. Поэтому если переменной йеу нет в массиве 11аа, то программа завершится ошибкой выхода значения индекса за пределы допустимого диапазона. Программа также завершится сообщением об ошибке индексирования при превышении счетчиком 1паех верхней границы индекса, равной 11ас1еп, т е.
при обращении к элементу 11аг [11вг1еп+1] . Если в языке предусмотрено и используется сокращенное вычисление булевских выражений, то это не проблема. В предыдущем примере схема сокращенного вычисления определит значение первого операнда оператора А(ЧО, и если он окажется ложным, то вычисление второго операнда будет пропущено. Сокращенное вычисление выражений поднимает проблему разрешения в выражениях побочных эффектов.
Предположим, что в выражении используется сокращенное вычисление, и не была вычислена часть выражения. вызывающая побочный эффект; побочный эффект проявится только позднее. при вычислении всего выражения. Если правильность работы программы зависит от этого побочного эффекта, то сокращенное вычисление может привести к серьезной ошибке. Рассмотрим след)юшее выражение на языке С; (а > Ь) ! ! (Ь++ / 3) В этом выражении изменение переменной Ь во втором арифметическом выражении происходит только при условии а <= Ь.
Если программист предполагал, что переменная Ь будет изменяться при каждом вычислении значения выражения, то программа будет работать неправильно. В языке Моди]а-2 каждое вычисление выражений, содержащих операторы А)чо и ОР, является сокращенным. В описании языка РОСТКАХ 77 эта проблема признана, и принято, что разработчик средств реализации может не вычислять выражений больше. чем нужно для определения результата. При этом отмечается. что если невычисляемой частью выражения является вызов функции, выполнение которой присваивает значение любой переменной, объявленной вне функции. то при сокращенном вычислении эта переменная должна устанавливаться в "неопределенное" состояние. Правда, при реализации этого правила возникают проблемы, основной из которых является сложность выявления любого существенного функционального побочного эффекта.
292 Глава 6. Выражения и операторы присваивания Язык А((а позволяет программисту задавать сокращенное вычисление булевских опе-.:- 1ров А(я() и ОК, используя лвусложные операторы апс( сЬеп и ок е1ве. Предпо. «им. что ЫЯТ вЂ” это массив с диапазоном индексов 1 .. 1.15ТЕЕ)Е тогда программа -.
языке Ая(а "«ЕХ: = 1 иоз1е (1)яЭЕХ <= ЫЯТЕЕВ) ап<1 сЬеп (ЫЯТ (1)(ВЕХ] /= КЕУ) 1оор 1(я()ЕХ := 1(ЧВЕХ + 1; епс( 1оор; -; приведет к ошибке в отсутствие переменной КЕТ в массиве ' 15Т и при превышении .етчиком 1(я()ЕХ значения Ы ЯТ' ЕМ. В языках С. С «я- и За«а обычные операторы логических И и ИЛИ.
ь ь и ( (, соответ.. а<нно, мо(ут вычисляться сокращенно. Кроме того, в этих языках существуют побитое операторы логических И и ИЛИ, ь и ), соответственно, которые, не вычисляясь со. гзшенно, могут использоваться в булевских выражениях. 6.7. Операторы присваивания Как отмечалось ранее. присваивание является одной из центральных конструкпий в чперативных языках программирования. Оно обеспечивает механизм, с помощью ко- Рого пользователь может динамически изменять связи значений с переляенными. В ;.;езуюшем разделе рассмотрена простейшая форма присваивания, а далее следует опи: лине различных альтернатив.
6.7.1. Простые присвоивоиив Общий синтаксис простого присваивания выглядит следующим образом; <"елевая переменная> <оператор присваивания> <выражение> В качестве оператора присваивания в языках ЕОКТЕА)л(, ВАЯ(С, РЕ/!. С. С.«+ и За«а использован знак равенства. Если этот же знак параллельно используется в качестве опегзтора отношения, что справедливо для языков Рь)( и ВАЯ)С, то может возникнуть пу-зница.
Например, в выражении языка РьЛ В =- С переменной А присваивается булевское значение выражения отношения В = С, хотя, на первый взгляд. все три переменные приравниваются друг к другу. В других языках, использующих знак - в качестве оператора присваивания. лля оператора отношения равенства используется другой оператор, что позволяет избежать перегрузки оператора присваивания. В языке АЕООЕ60 впервые в качестве оператора присваивания был использован знак: =, и многие последую~дне языки эту форму переняли. Оператор присваивания в языках С, Ся-«и 3аэа интсрпретируегся как бинарный оператор, и в таком качестве он появляется в выражениях.
Подробнее об этом операторе рассказывается в разделе 6.7.6. Существует множество разнообразных проектных решений относительно использования присваивания в языке. В языках РОКТКАН, Разса( и Ада оно может появляться 293 6.7. Операторы присваивания только в качестве самостоятельного оператора, и его целевой объект ограничен одной переменной. Существует, правда, множество альтернатив.
6.У.2. Множественные целевые объекты Одной из альтернатив простого оператора присваивания является возможность присваивания значения выражения нескольким объектам. Например, в языке Р1Л оператор Б))М, ТОТАЬ = О одновременно присваивает нулевое значение переменным ВВМ и ТОТАЬ. Присвоение значений нескольким целевым объектам удобно, но не очень важно. Эффекта множественного присваивания можно добиться с помощью оператора присваивания в языках С, С++ и 3ача, как показано в разделе 6.7.6. 6.У.З.
Условные целевые объекты Языки С++ и Зача допускают использование в операторах присваивания условных целевых объектов. Например, выражение Т1ад ? соипС1 : соппт2 = О эквивалентно следующему: ЬЕ (Т1ац) соппт1 = О; в1вв соипт2 = О 6.У.Я. Составные операторы присваивания Составной оператор присваивания позволяет сокращенно задавать часто используемую форму присваивания. С помощью этого метода можно сократить запись присваивания, прн котором целевая переменная используется в качестве первого операнда в правой части выражения, например: а = а+Ь Составные операторы присваивания впервые появились в языке АОЬОЕ 63, а позже в несколько видоизмененной форме перешли в язык С. Синтаксис составного оператора присваивания языка С представляет собой объединение нужного бинарного оператора и оператора =.
Например, выражение ащв + ча1иег эквивалентно выражению впм = вщл + ча1иег В языках С, С++ и Зача версии составных операторов присваивания существуют для большинства бинарных операторов этих языков. 6.У.5. Упорные операторы присваивания В языках С, С++ и влача есть два специальных унарных арифметических оператора, представляющих собой действительно сокращенные присваивания. Эти операторы сочетают операции увеличения и уменьшения с присваиванием. Операторы ++ для увеличения и -- для уменьшения могут использоваться как в выражениях, так и для выполнения Глава 6. Выражения и опврпторы присваивания присваивания.
Они могут появляться как префиксные операторы (т.е. перед операндами) нли как постфиксные (т.е. после операндов). В операторе присваивания 5цтв ++ соцпс' Значение переменной соипт увеличивается на 1 и присваивается переменной эшж То же самое действие можно задать следующими операторамн: соипс = соцпс + 1; эша - соцпст Постфиксный оператор 5ЦБ = СОСПС вначале присваивает значение переменной соипс переменной эцв, после чего переменная соипс увеличит свое значение на 1.
То же действие можно задать следующими операторами: вцтв - соцпст соцпт = соцпг + 1; Ниже приведен пример использования оператора инкрементации для формирования завершенного оператора присваивания соцпс значение переменной соцпс в нем просто увеличивается на 1. Хотя это и не выглядит присваиванием, но оно таковым является.