Перейти к содержимому
Теория · Операторы и выражения · урок 3 из 8

Сравнения, логика, ++ и --

Программе постоянно нужны ответы «да или нет»: совершеннолетний ли пользователь, попадает ли число в диапазон. Такой ответ даёт сравнение, и его результат имеет тип bool:

C++
#include <iostream>

int main() {
    int age = 20;
    bool adult = age >= 18;
    bool teen = age >= 13 && age <= 19;
    std::cout << adult << ' ' << teen << '\n';  // 1 0
}

std::cout печатает true как 1, а false — как 0. Переменная teen равна false: 20 <= 19 неверно, а && требует, чтобы были верны обе части.

Сравнения

Основных операторов сравнения шесть:

  • == — равно;
  • != — не равно;
  • < — меньше;
  • <= — меньше или равно;
  • > — больше;
  • >= — больше или равно.

Равенство проверяет двойной знак ==, а одиночный = присваивает значение. Сравнивать можно и числа разных типов: 2 < 2.5 даёт true, потому что 2 сначала преобразуется в double.

Логические операторы

Логических операторов три:

  • && (И) даёт true, когда верны оба операнда;
  • || (ИЛИ) даёт true, когда верен хотя бы один;
  • ! (НЕ) меняет true на false и обратно: !(age >= 18) верно для несовершеннолетнего.

Число в роли операнда &&, || или ! превращается в bool: 0 даёт false, а любое другое число — true.

&& и || сначала вычисляют левый операнд. Если по нему ответ уже ясен, правый не вычисляется вовсе. Для && это левый false, для || — левый true. Такой пропуск правого операнда называют коротким замыканием:

C++
#include <iostream>

bool is_even(int n) {
    std::cout << "is_even(" << n << ")\n";
    return n % 2 == 0;
}

int main() {
    bool a = is_even(3) && is_even(4);  // is_even(3)
    bool b = is_even(4) || is_even(3);  // is_even(4)
    std::cout << a << ' ' << b << '\n';  // 0 1
}

Вызовов is_even(4) в первой строке и is_even(3) во второй не было: ответ уже дала левая часть. Поэтому правый операнд может рассчитывать на то, что левый уже верен: в d != 0 && n / d > 2 деления на ноль не будет.

Операторы ++ и --

++a увеличивает переменную на единицу, а --a уменьшает. У каждого из этих операторов две формы. Префиксная форма ++a сначала увеличивает a и возвращает новое значение. Постфиксная форма a++ тоже увеличивает a, но возвращает старое:

C++
int a = 5;
int b = a++;
int c = ++a;
std::cout << a << ' ' << b << ' ' << c << '\n';  // 7 5 7

b получила 5 — значение a до первого увеличения. Если результат не используется, как в отдельной инструкции ++a;, формы ничем не отличаются. Похожая краткая запись есть и у других операций: a += 5 значит a = a + 5, а -=, *=, /= и %= работают так же.

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

Проверку, попадает ли число в диапазон, новички записывают так же, как в математике:

C++
#include <iostream>

int main() {
    int x = 15;
    bool in_range = 0 < x < 10;  // ✗
    std::cout << in_range << '\n';  // 1
}
TEXT
warning: result of comparison of constant 10 with expression of type 'bool' is always true [-Wtautological-constant-out-of-range-compare]

Компилятор только предупреждает. Выражение читается как (0 < x) < 10: 0 < x даёт true или false, то есть 1 или 0, а и 1 < 10, и 0 < 10 верны. Поэтому результат true при любом x. Диапазон проверяют двумя сравнениями: 0 < x && x < 10.

Главное

  • Сравнение даёт bool, а равенство проверяет ==, не =.
  • && и || не вычисляют правый операнд, когда ответ ясен по левому.
  • a++ возвращает старое значение, а ++a — новое.
  • Диапазон проверяют двумя сравнениями: 0 < x && x < 10.

Подпишись, чтобы пройти курс

Курс бесплатный. Войди через Telegram и подпишись на канал — откроются все уроки.

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