if, else и if с инициализатором
Чему вы научитесь:
- выбирать, какой код выполнить, с помощью
if,else ifиelse; - видеть, к какому
ifотноситсяelse, и не попадаться на висячийelse; - объявлять переменную прямо в
ifи понимать, где она видна; - выбирать ветку по значению с помощью
switchи не забыватьbreak.

Представьте развилку дороги с указателем: «Если идёт дождь — налево, к остановке, иначе — направо, через парк». Вы читаете условие и выбираете одну дорогу, а по второй в этот раз не идёте. Программе тоже нужны такие развилки: напечатать одно или другое, посчитать так или иначе.
Инструкции в main выполняются по порядку, сверху вниз. Инструкция if выполняет блок в фигурных скобках, только если условие в круглых скобках истинно. Блок после else выполняется, когда условие ложно:
#include <iostream>
int main() {
int t = 25;
if (t < 0) {
std::cout << "frost\n";
} else if (t < 20) {
std::cout << "cool\n";
} else {
std::cout << "warm\n"; // warm
}
}Давайте пройдём по программе:
int t = 25;— переменнаяtравна25.if (t < 0)— условие ложно, поэтому программа пропускает первый блок.else if (t < 20)— это условие тоже ложно.else— остаётся последний блок, и программа печатаетwarm.
Ветки и их порядок
Каждый такой блок называют веткой. Цепочка else if проверяет условия сверху вниз и выполняет первую ветку, чьё условие истинно, а остальные пропускает. Поэтому порядок веток важен: вторая ветка проверяется только при t >= 0, когда первое условие уже ложно.
Ветка else стоит последней и срабатывает, когда ложны все условия выше. Без неё, когда все условия ложны, не выполнится ни одна ветка.
Здесь развилка отличается от настоящей дороги: путник может выбрать самый подходящий указатель, а программа читает их строго сверху вниз и идёт по первому подходящему.
Висячий else
Фигурные скобки вокруг ветки из одной инструкции можно не писать. Но когда два if вложены друг в друга без скобок, читатель может решить, что else относится к другому if. Компилятор относит else к ближайшему if, у которого ещё нет своего else, а на отступы не смотрит:
int x = 5;
if (x > 0)
if (x > 10)
std::cout << "big\n";
else // ✗
std::cout << "not positive\n"; // not positiveПо отступам else принадлежит if (x > 0), но на деле он достался if (x > 10). Давайте разберём, что происходит при x = 5:
if (x > 0)— условие истинно, программа входит во внутреннийif.if (x > 10)— условие ложно, поэтому выполняется егоelse.- Программа печатает
not positive, хотяxположительный.
Такой else называют висячим. Clang и GCC предупреждают о нём, но код компилируется. Этот пример часто показывают на собеседовании и спрашивают, что напечатает программа.
Ставьте фигурные скобки у каждой ветки, даже из одной строки: тогда компилятор и читатель видят одни и те же ветки.
if с инициализатором
Переменную, нужную только для проверки, можно объявить прямо в if — перед условием, через точку с запятой. Эту часть if называют инициализатором. Объявленная в нём переменная видна в условии и во всех ветках этого if:
int n = 2023;
if (int r = n % 4; r == 0) {
std::cout << "divisible by 4\n";
} else {
std::cout << "remainder " << r << '\n'; // remainder 3
}После if переменной r уже нет: код, который обращается к ней ниже, не скомпилируется. Поэтому ниже в той же функции можно объявить другую переменную с именем r.
Частая ошибка
К ветке без фигурных скобок дописали вторую строку с тем же отступом:
int x = -1;
if (x > 0)
std::cout << "positive\n";
std::cout << "checked\n"; // ✗warning: misleading indentation; statement is not part of the previous 'if' [-Wmisleading-indentation]Без скобок if управляет только одной следующей инструкцией, и отступ этого не меняет. Поэтому checked печатается при любом x, в том числе при x = -1. Компилятор лишь предупреждает и собирает программу. Исправление — фигурные скобки вокруг обеих строк.
Главное
- Цепочка
if/else if/elseвыполняет первую ветку с истинным условием и пропускает остальные. elseотносится к ближайшемуifбез своегоelse, а отступы на это не влияют.- Без фигурных скобок
ifуправляет только одной инструкцией, поэтому скобки ставят у каждой ветки. - Переменная из инициализатора
ifвидна в условии и во всех ветках, но не послеif.
Подпишись, чтобы пройти курс
Курс бесплатный. Войди через Telegram и подпишись на канал — откроются все уроки.