Перейти к содержимому
Topos Uranos

Выражения и операторы: итоги и задачи повышенной трудности

Краткое содержание

Этот урок завершает третий раздел курса, посвящённый выражениям и их операторам. Он восстанавливает цепочку понятий, которая ведёт от арифметического оператора к библиотечной функции через дерево выражения и тип каждого узла, условия и их алгебру, вычисление по короткой схеме, побочный эффект и порядок вычисления, а также биты; отделяет то, что из этого верно в любом языке, от того, что свойственно C++; собирает неопределённое поведение раздела вместе с тем, что обнаруживает компилятор, что обнаруживает санитайзер и чего не обнаруживает никто; повторяет в итоговой проверке умения входной; и заканчивается шестью задачами повышенной трудности, которые объединяют весь раздел.

Цели обучения

  1. Предсказывать значение, тип и эффект любого выражения курса по его дереву и по преобразованиям в каждом узле.
  2. Записывать и отрицать составные условия и пользоваться короткой схемой, чтобы защитить операцию, которая иначе была бы лишена смысла.
  3. Распознавать выражения, лишённые смысла (каталог неопределённого поведения раздела), называть инструмент, который обнаруживает каждое из них, и переписывать их без него.
  4. Выбирать для данного вычисления между арифметикой, побитовыми операторами и математической библиотекой и обосновывать выбор.
  5. Отделять в изученном в разделе то, что верно в любом языке, от того, что свойственно C++.

Чего достиг раздел

Раздел ставил целью научить строить выражения, значение которых можно предсказать с уверенностью: какая операция выполняется первой, какого типа результат, какие у него побочные эффекты и какие выражения не имеют смысла. Цель достигнута с опорой лишь на то, что введение объявило известным: типы раздела 2, их диапазоны значений и их преобразования. Программу с шестью вопросами, которой введение поставило задачу, теперь можно прочитать так, как её читает компилятор, и исправить выражение за выражением.

Арифметические операции

Урок Арифметические операции установил точное поведение пяти арифметических операторов. Целочисленное деление округляет к нулю и выполняет тождество (a / b) * b + a % b == a всякий раз, когда частное имеет смысл, так что остаток, когда он не равен нулю, имеет знак делимого; поэтому -7 / 2 равно −3-3, а -7 % 2 равно −1-1, и нечётность выясняют выражением n % 2 != 0. Урок связал это с евклидовым остатком, ((a % b) + b) % b при b>0b > 0, и применил оба остатка, чтобы раскладывать величины. Он научил рисовать дерево выражения по приоритету и ассоциативности и определять тип в каждом узле по обычным арифметическим преобразованиям. Завершился он частными без смысла (целочисленным делением на ноль и делением наименьшего целого на −1-1) и переполнением промежуточного результата, которого достаточно для неопределённого поведения, даже если окончательный результат помещается.

Отношения и логика

Урок Отношения и логика показал, что условие есть выражение типа bool со своим местом в дереве: сравнения связывают слабее арифметики, && сильнее, чем ||, а ! сильнее всех. Он научил переводить формулировки в условия и распознавать те, что компилируются с другим смыслом, как 1 < x < 5 и day == 6 || 7. Он показал, что && и || вычисляют свой второй операнд, только если первый не решает дело, и что эта короткая схема позволяет защитить операцию стражем слева от неё. Закончился он законами де Моргана, которые отрицают составное условие, и их границей: при нечисловом значении !(a < b) не равносильно a >= b.

Присваивание, побочные эффекты и неопределённое поведение

Урок Присваивание, побочные эффекты и неопределённое поведение отличил значение выражения от его эффекта: присваивание есть выражение, которое равно присвоенному и меняет переменную, а x++ равно прежнему значению, тогда как ++x равно новому. Он показал, что дерево выражения не задаёт порядок, в котором вычисляются его ветви, так что два эффекта над одной переменной, или эффект и чтение, без порядка между ними лишают выражение смысла, и уточнил, что упорядочил C++17 и что оставил неуточнённым. Он собрал каталог четырёх ступеней (определённое, определяемое реализацией, неуточнённое и неопределённое поведение), объяснил, что компилятор рассуждает в предположении, что в программе нет неопределённого поведения, и указал для каждого случая каталога, какой инструмент его обнаруживает.

Биты и математическая библиотека

Урок Биты и математическая библиотека показал, что целое число есть также последовательность битов: &, | и ^ применяют связку к каждому столбцу, ~ инвертирует все биты, а сдвиги умножают и делят на степени 2 при условии, что величина сдвига не отрицательна и не достигает ширины типа. С их помощью он построил маски, которые проверяют, устанавливают, сбрасывают и переключают бит. Он предупредил, что эти операторы связывают слабее сравнений, так что x & 1 == 0 спрашивает не то, что кажется, и что ^ не есть возведение в степень. Завершился он библиотекой: <cmath>, <numbers>, <numeric> и <bit> дают правильные и испытанные вычисления со своими предусловиями, как предусловие модуля числа, который не существует для наименьшего целого.