if, else и if с инициализатором
Инструкции в 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
}
}Каждый такой блок называют веткой (branch). Цепочка else if проверяет условия сверху вниз и выполняет первую ветку, чьё условие истинно, а остальные пропускает. Ветка else в конце срабатывает, когда ложны все условия. Без неё в этом случае не выполнится ничего.
Висячий else
Фигурные скобки вокруг ветки из одной инструкции можно не писать. Но когда два if вложены друг в друга без скобок, else можно по ошибке приписать не тому if. Компилятор (compiler) относит 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 программа печатает not positive. Такой else называют висячим (dangling else). Clang и GCC предупреждают о нём, но код компилируется.
Ставьте фигурные скобки у каждой ветки, даже из одной строки: тогда компилятор и читатель видят одни и те же ветки.
if с инициализатором
Переменную, нужную только для проверки, можно объявить прямо в if — перед условием, через точку с запятой. Эту часть if называют инициализатором (initializer). Объявленная в нём переменная видна в условии и во всех ветках этого 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. Компилятор лишь предупреждает и собирает программу. Исправление — фигурные скобки вокруг обеих строк.