Перейти к содержимому
Теория · Условия · урок 1 из 6

if, else и if с инициализатором

Чему вы научитесь

Чему вы научитесь:

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

Представьте развилку дороги с указателем: «Если идёт дождь — налево, к остановке, иначе — направо, через парк». Вы читаете условие и выбираете одну дорогу, а по второй в этот раз не идёте. Программе тоже нужны такие развилки: напечатать одно или другое, посчитать так или иначе.

Инструкции в main выполняются по порядку, сверху вниз. Инструкция if выполняет блок в фигурных скобках, только если условие в круглых скобках истинно. Блок после else выполняется, когда условие ложно:

C++
#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
    }
}

Давайте пройдём по программе:

  1. int t = 25; — переменная t равна 25.
  2. if (t < 0) — условие ложно, поэтому программа пропускает первый блок.
  3. else if (t < 20) — это условие тоже ложно.
  4. else — остаётся последний блок, и программа печатает warm.

Ветки и их порядок

Каждый такой блок называют веткой. Цепочка else if проверяет условия сверху вниз и выполняет первую ветку, чьё условие истинно, а остальные пропускает. Поэтому порядок веток важен: вторая ветка проверяется только при t >= 0, когда первое условие уже ложно.

Ветка else стоит последней и срабатывает, когда ложны все условия выше. Без неё, когда все условия ложны, не выполнится ни одна ветка.

Здесь развилка отличается от настоящей дороги: путник может выбрать самый подходящий указатель, а программа читает их строго сверху вниз и идёт по первому подходящему.

Висячий else

Фигурные скобки вокруг ветки из одной инструкции можно не писать. Но когда два if вложены друг в друга без скобок, читатель может решить, что else относится к другому if. Компилятор относит else к ближайшему if, у которого ещё нет своего else, а на отступы не смотрит:

C++
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:

  1. if (x > 0) — условие истинно, программа входит во внутренний if.
  2. if (x > 10) — условие ложно, поэтому выполняется его else.
  3. Программа печатает not positive, хотя x положительный.

Такой else называют висячим. Clang и GCC предупреждают о нём, но код компилируется. Этот пример часто показывают на собеседовании и спрашивают, что напечатает программа.

Ставьте фигурные скобки у каждой ветки, даже из одной строки: тогда компилятор и читатель видят одни и те же ветки.

if с инициализатором

Переменную, нужную только для проверки, можно объявить прямо в if — перед условием, через точку с запятой. Эту часть if называют инициализатором. Объявленная в нём переменная видна в условии и во всех ветках этого if:

C++
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.

Частая ошибка

К ветке без фигурных скобок дописали вторую строку с тем же отступом:

C++
int x = -1;
if (x > 0)
    std::cout << "positive\n";
    std::cout << "checked\n";  // ✗
TEXT
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 и подпишись на канал — откроются все уроки.

Войти другим способом