Группировка с помощью круглых скобок

В предыдущих разделах мы уже не раз видели, что некоторые выражения могут вызывать неожиданные результаты из-за приоритетов операций. Для явного изменения порядка расчета необходимо пользоваться круглыми скобками. Заключенная в них часть выражения получает повышенный приоритет по сравнение с окружением, невзирая на приоритеты по умолчанию. Пары скобок могут быть вложенными, однако делать уровень вложенности больше 3-4 не рекомендуется. Слишком сложные выражения лучше разделить на несколько отдельных.

В скрипте ExprParentheses.mq5 показана эволюция расстановки скобок в одном выражении. Исходный замысел для него в том, чтобы взвести бит в переменной flags с помощью операции сдвига влево '<<'. Номер бита берется из переменной offset, если она не нулевая, или равным 1 в противном случае (напомним, нумерация идет с нуля). Затем полученное значение умножается на coefficient. Прикладного смысла в этом примере искать не стоит, но на практике встречаются и более хитрые конструкции.

int offset = 8;
int coefficient = 10flags = 0;
int result1 = coefficient * flags | 1 << offset > 0 ? offset : 1;     // 8
int result2 = coefficient * flags | 1 << (offset > 0 ? offset : 1);   // 256
int result3 = coefficient * (flags | 1 << (offset > 0 ? offset : 1)); // 2560

Первый вариант без скобок кажется подозрительным даже компилятору. Тот выдает уже знакомое нам предупреждение "выражение не является логическим" ("expression not boolean"). Дело в том, что минимальным приоритетом из всех операторов здесь обладает тернарный условный. Из-за этого вся левая часть до знака '?' считается его условием. Внутри условия вычисления идут в следующем порядке: умножение, побитовый сдвиг, сравнение "больше", побитовое ИЛИ, в результате чего получается целое число. Оно, конечно, может использоваться как true или false, но такие намерения желательно всегда "сообщать" компилятору с помощью явного приведения типов. В его отсутствии компилятор считает выражение подозрительным, и не зря. Результат первого расчета равен 8. Он неверный.

Добавим скобки вокруг тернарного оператора. Предупреждение компилятора пропадет. Однако выражение по-прежнему считается неправильно. Поскольку приоритет умножения выше побитового ИЛИ, переменные coefficient и flags перемножаются до того, как применяется битовая маска, получаемая сдвигом влево. Результат равен 256.

Наконец, добавив еще одни скобки, мы получим правильный результат 2560.