Лабораторная работа оператор присваивания. Оператор
![]()
|
ЛАБОРАТОРНАЯ РАБОТА 2. ОПЕРАТОР ПРИСВАИВАНИЯ. ОПЕРАТОР ВЕТВЛЕНИЯ. ОПЕРАТОР ВЫБОРА Тщательно пережевывайте пищу, этим вы помогаете обществу. И.Ильф и Е.Петров ОБЯЗАТЕЛЬНЫЕ РЕЗУЛЬТАТЫ ОБУЧЕНИЯ Знать понятия: • "оператор"; • "пустой оператор", "оператор присваивания"; • "операция присваивания", "операции отношения", "логические операции", "условная операция", "операция "запятая""; • "преобразование типов"; • "оператор увеличения", "оператор уменьшения", "оператор ветвления if/else", "оператор выбора switch". Уметь: • реализовывать алгоритмы, содержащие оператор присваивания, оператор ветвления и оператор выбора. ТЕОРЕТИЧЕСКИЕ СВЕДЕНИЯ Понятие "оператор" Операторы являются единицами выполнения программы. Программа на языке C состоит из последовательности операторов. Последним символом оператора является символ "точка с запятой". Таким образом, в языке C символ ";" служит признаком конца оператора, а не разделителем операторов (например, в языке Pascal). Определение. (1) Составной оператор — это последовательность операторов, заключённая в фигурные скобки "{" и "}". (2) Блок — это совокупность описаний и операторов, заключённых в фигурные скобки. Нетрудно видеть, что каждая функция языка C представляет собой блок, который предваряет заголовок - имя функции и параметры. Итак, все конструкции, заключенные в фигурные скобки, являются синтаксически эквивалентными одному оператору. Замечание. Состояние программы — это совокупность всей информации, которая может изменяться во время выполнения программы. Состояние программы для императивного стиля программирования содержит: (1) совокупность значений всех глобальных переменных и содержимого динамической памяти; (2) содержимое регистров общего назначения; (3) содержимое стека (включая адреса возвратов и значения локальных переменных); (4) текущее значение счётчика команд (т.е. текущей позиции в коде программы). Состояние программы содержит явную часть (значения переменных) и неявную часть (адреса возвратов и значение счётчика команд). Пустой оператор (NULL-команда) Определение [Жешке,1994] (синтаксис пустого оператора). NULL-команда — это команда, состоящая только из символа ";". Прагматика пустого оператора. Пустой оператор используется для обозначения пустого тела прочих операторов языка C: if/else, switch, while, do/while, for. Операции языка C 1. Операция присваивания. Оператор присваивания Определение. (1) Операция присваивания имеет следующий синтаксис: <Адресуемое_значение>=<Выражение>, где <Адресуемое_значение> (называемое также l-значением) – это ссылка на объект, которой может являться: (а) идентификатор; (б) ссылка на элемент массива (см. далее); (в) ссылка на элемент структуры (см. далее). (2) r-значением (r-value) называется <Выражение>, которое соответствует значению некоторого типа, но не обязательно обозначает объект. Операционная семантика операции присваивания такова: (1) вычисляются значения конструкций <Выражение> и <Адресуемое_значение>; (2) результатом операции присваивания становится значение конструкции <Выражение>; (3) результат вычисления конструкции <Выражение> становится значением объекта, расположенного по адресу <Адресуемое_значение>. Примеры. 1. Синтаксическая конструкция языка С legs=(4+5)/3 является операцией присваивания, значением которой является значение выражения (4+5)/3 (т.е. 3), а переменная с именем legs получит значение 3. 2. Рассмотрим выражение (x=5)*2+7. Вначале выполняются действия в скобках: переменная x получает значение 5; это значение участвует в дальнейших вычислениях: выполняется умножение (5*2), затем сложение (10+7), и значением всего выражения станет 17. Таким образом, в отличие от многих языков программирования высокого уровня, в языке C операция присваивания является выражением и возвращает значение (как обычно для операции в программировании). Оператор присваивания является основной "рабочей силой" практически всех программ на языке C. Определение (синтаксис оператора присваивания). Оператор присваивания имеет следующий синтаксис: <Адресуемое_значение>=<Выражение>; где <Адресуемое_значение> (называемое также l-значением) – это ссылка на объект, которой может являться: (а) идентификатор; (б) ссылка на элемент массива (см. далее); (в) ссылка на элемент структуры (см. далее). Таким образом, оператор присваивания синтаксически состоит из операции присваивания и символа ';'. Определение (семантика оператора присваивания). Операционная семантика оператора присваивания такова: (1) вычисляются значения конструкций <Выражение> и <Адресуемое_значение>; (2) результат вычисления конструкции <Выражения> помещается по адресу <Адресуемое_значение>. Пример. Опишем операционную семантику следующего оператора присваивания: a=(y=(x=5)*2+7)/4; Вначале выполняется операция присваивания в самых внутренних скобках: в результате переменная x получает значение 5, и это значение участвует в дальнейших вычислениях. Затем выполняются следующие операции: умножение (5*2), сложение (10+7) и присваивание (y=17). Переменная y получает значение 17, после чего производится деление (17/4), результат которого присваивается переменной a. Работа с демонстрационными примерами См. Пример 1, Пример 2. 2. Специальные формы операции присваивания Выше мы привели две специальные формы операции присваивания: арифметические операции увеличения и уменьшения на единицу (++ и --). Продолжим рассмотрение специальных форм. Определение (специальные формы операции присваивания). Специальными формами операции присваивания называются операции со следующими знаками операций: (1) арифметические: += (сложение с присваиванием); -= (вычитание с присваиванием); *= (умножение с присваиванием); /= (деление с присваиванием); %= (остаток от деления с присваиванием); >>= (сдвиг влево с присваиванием); <<= (сдвиг вправо с присваиванием); (2) логические: &= (битовое "И" с присваиванием); |= (битовое "ИЛИ" с присваиванием); ^= (битовое исключающее "ИЛИ" с присваиванием). Определение (операционная семантика специальных форм операции присваивания). Если λ - какой-либо из знаков арифметической или логической операции, а В 1 и В 2 - выражения, то результаты выполнения операций присваивания В 1 𝜆 = В 2 и В 1 = В 1 𝜆В 2 одинаковы (другими словами, указанные операции семантически эквивалентны). Пример. Выражения i+=2 и i=i+2 семантически эквивалентны. Работа с демонстрационными примерами См. Пример 3. 3. Операции отношения Все животные равны. Но некоторые животные более равны, чем другие. Дж.Оруэлл. Скотный двор Определение. Операциями отношения называются бинарные операции, возвращающие значения из множества {0,1} и имеющие следующие имена: == (равно); != (не равно); > (больше); < (меньше); >= (больше или равно); <= (меньше или равно) Операнды операций отношения называются "истиной" (это любое ненулевое значение) и "ложью" (это целое нулевое значение). Значением выражений, содержащих операции отношения, является 0 ("ложь") или 1 ("истина") (что, впрочем, вполне естественно). Замечания. 1. Главное предостережение состоит в том, чтобы Вы по ошибке не использовали знак "=" вместо знака "==". С помощью операции присваивания некоторое значение присваивается переменной, идентификатор которой расположен слева от знака равенства. В то же время с помощью операции отношения проверяется, равно ли значение выражения, расположенного слева от знака "==", значению выражения, стоящему справа. Например, операция присваивания can=3 присваивает значение 3 переменной can, а операция отношения can==3 проверяет, равняется ли значение переменной can 3. В ряде случаев компилятор не сможет обнаружить ошибок, связанных с неправильным использованием знаков этих операций, что приведёт к результатам, отличным от ожидаемых. Чтобы избежать подобной ловушки, некоторые программисты советуют писать константу слева, а переменную - справа: if (0==x) Тогда условие с одним знаком "=" будет ошибочным, и компилятор это сразу обнаружит. 2. Старайтесь избегать сравнения двух вещественных значений a и b на равенство, т.к. "теоретически" равные вещественные числа после серии вычислений будут равны друг другу лишь приблизительно. Вместо отношения a==b следует использовать отношение вида abs(a-b) Если порядок чисел a и b неизвестен, то Epsilon должна быть функцией одного из них. Например, выражение abs(a-b) 3. В некоторых других языках программирования (например, BASIC) один и тот же знак используется и для операции присваивания, и для операции отношения "равенство". Работа с демонстрационными примерами См. Пример 4. 4. Логические операции Если Вы совсем не знакомы с логическими операциями или испытываете трудности при работе с ними, помните, что Практика&&Время==Совершенство М.Уэйт, С.Прата, Д.Мартин Определение. Логическими операциями называются операции, имеющие тип {0,1} 𝑛 → {0,1}, 𝑛 = 1,2, и следующие имена: ! (логическое отрицание, n=1); || (логическое "ИЛИ", n=2); && (логическое "И", n=2). Определение (семантика логических операций). (1) Операция отрицания ! преобразует ненулевой операнд ("истинный") в 0, а нулевой операнд ("ложный") - в 1. (2) Логическая операция || возвращает значение 0, если оба её операнда имеют значение 0, иначе она возвращает значение 1. (3) Логическая операция && возвращает значение 1, если оба её операнда имеют значение 1, иначе она возвращает значение 0. (4) Логические выражения, связанные логическими операциями && и ||, вычисляются в направлении слева направо, причём вычисление значения выражения прекращается сразу же, как только становится ясно, будет ли результат 0 или 1. Замечание (важное). Логическое выражение !inword имеет такую же операционную семантику, как и операция отношения inword==0. Работа с демонстрационными примерами См. Пример 5. 5. Условная операция Ключом ко всякой науке является вопросительный знак. Оноре де Бальзак Определение (синтаксис условной операции). Условной операцией называется трёхместная операция со следующим синтаксисом: <Условие>?<Выражение_1>:<Выражение_2> Определение (операционная семантика условной операции). Вычисляется значение выражения <Условие>: если значение отлично от нуля ("истинно"), то вычисляется значение выражения <Выражение_1>, которое и становится значением условной операции, в противном случае вычисляется значение выражения <Выражение_2>, и оно становится значением условного выражения. Примеры. 1. Выражение (5>3)?1:2 возвращает значение 1, а выражение (3>5)?1:2 возвращает значение 2. 2. Выражение (a>b)?a:b возвращает большее из значений a и b. 3. После выполнения операции присваивания x=(y<0)?-y:y значением переменной x становится абсолютная величина значения y. Замечания (прагматические). 1. Условную операцию удобно использовать в тех случаях, когда некоторой переменной необходимо присвоить одно из двух значений. 2. Использование условной операции не является обязательным, поскольку тех же результатов можно достичь при помощи оператора if/else (см. далее). Например, оператор x=(y<0)?-y:y; может выглядеть так: if (y<0) x=-y; else x=y; Однако условная операция более компактна, а её применение обычно приводит к получению более компактного машинного кода. Работа с демонстрационными примерами См. Пример 6. 6. Операция "запятая" Не следует быть погребённым под бумагами; надо найти людей, которые их распутают. Следует управлять делами одним жестом, знаком; уметь поставить запятую, которая определяет смысл. Шарль-Морис де Талейран Определение (синтаксис операции "запятая"). Операция "запятая" имеет следующий синтаксис: <Выражение_1>,<Выражение_2>,…,<Выражение_N> Определение (операционная семантика операции "запятая"). Значения выражений, разделённых запятыми, вычисляются слева направо. Типом и значением результата являются тип и значение выражения <Выражение_N>. Иногда [Шилдт,2002,с.75] операция "запятая" называется операцией последовательного вычисления. Замечания (прагматические). 1. Операция "запятая" особенно часто используется в циклах for. 2. Символ "запятая" также используется как разделитель. Например, запятые в конструкциях языка C char ch,date; и printf("%d %d",a,b); являются разделителями, а не знаками операции "запятая". Работа с демонстрационными примерами См. Пример 8. 7. Выполнение операций и их приоритеты М *** задали каверзный вопрос. "Есть вещи, - ответил он, - которые я отлично помню, пока никто не заговаривает со мной о них, но мгновенно забываю, едва меня начинают расспрашивать". Себастьен Шамфор. Характеры и анекдоты Для большинства операций порядок их выполнения определяется приоритетами, однако существуют исключения из этого правила: (1) префиксные операции увеличения и уменьшения, например ++x и --x, всегда выполняются прежде, чем их операнд будет использован в выражении; (2) постфиксные операции увеличения и уменьшения, например x++ и x--, всегда выполняются после того, как их операнд будет использован в выражении; (3) логические операции && и || всегда выполняются слева направо, причём значение логического выражения вычисляется слева направо до тех пор, пока не станет известно его значение. Преобразование типов 1. Неявное преобразование типов Если в выражении встречаются переменные и константы разных типов, то они преобразуются к одному типу. Компилятор преобразует "меньший" тип в "больший". Этот процесс называется продвижением типов. Сначала все переменные типов char и int автоматически продвигаются в int. Это называется целочисленным расширением. После этого все остальные операции выполняются одна за другой, как описано в алгоритме преобразования типов [Шилдт,2002,с.78]: Если операнд имеет тип long double то второй операнд преобразуется в long double иначе Если операнд имеет тип double то второй операнд преобразуется в double иначе Если операнд имеет тип float то второй операнд преобразуется в float иначе Если операнд имеет тип unsigned long то второй операнд преобразуется в unsigned long иначе Если операнд имеет тип long то второй операнд преобразуется в long иначе Если операнд имеет тип unsigned int то второй операнд преобразуется в unsigned int Кроме того, если один из операндов имеет тип long, а второй - unsigned int, притом значение unsigned int не может быть представлено типом long, то оба операнда преобразуются в тип unsigned long. После выполнения приведённых выше преобразований оба операнда относятся к одному и тому же типу, к этому типу относится и результат операции. Менее формально алгоритм преобразования типов можно описать так (правила неявного преобразования типов): (1) переменные типа char интерпретируются как целые без знака (unsigned); (2) переменные типа short автоматически преобразуются к типу int; если один из операндов имеет тип unsigned, то другой (другие) также преобразуется к типу unsigned и результат имеет тип unsigned; (3) если один из операндов имеет тип int, то другой (другие) также преобразуется к типу int и результат имеет тип int; (4) если один из операндов имеет тип char, то другой (другие) также преобразуется к типу char и результат имеет тип char; (5) во время операции присваивания значение правой части преобразуется к типу левой части, который и становится типом результата; (6) в процессе преобразования int в char "лишние" старшие 8 битов отбрасываются. |