C. Операторы
Время чтения: 6 минут
Оператор – это штука, с помощью которой можно совершить операцию (сложение, вычитание и т.д.)
Существует два вида операторов:
- Унарные – для операций над одной переменной
- Бинарные – для операций над двумя переменными
Есть ещё тернарный (с тремя переменными), но про него мы вспомним, когда будем говорить про условия (if, else).
Бинарные операторы
Начнём с бинарных, потому что они роднее и понятнее:
- Сложение: +
- Вычитание: -
- Умножение: *
- Деление: /
- Остаток от деления: %
Необходимо учитывать, что у операторов разные приоритеты применения – например, классический пример:
2 + 2 * 2 = ?
Если твой ответ 8, то ты забыл что умножение выполняется перед сложением. Здесь всё точно так же – сначала слева направо выполняются * / %, а затем так же выполняются + -.
Однако, как и в математике ты можешь ставить скобки, чтобы изменять порядок выполнения операций:
(2 + 2) * 2 = 8
Операторы можно использовать разными способами:
- С целочисленными значениями
- С вещественными значениями
- Со смешанными значениями
- С приведением типа
- С операцией присваивания
- Для злодеев
Да, в языке C многовато тонкостей с операторами, но это всё само запомнится со временем – просто попробуй уловить основные моменты.
С целочисленными значениями
Вот примеры использования операций с целочисленными значениями:
int a = 15, b = 8;
int result;
result = a + b; // Присвоится 23
result = a - b; // Присвоится 7
result = a * b; // Присвоится 120
result = a / b; // Присвоится 1 потому что получается 1.875, а так как это целое число (int) -- дробная часть просто отбросится
result = a % b; // Присвоится 7 потому что при делении 15 на 8 получается 1 целая часть, и 7 в остатке
result = a + b * 2; // Присвоится 31
result = (a + b) * 2; // Присвоится 46
С вещественными значениями
Вот примеры использования операций с вещественными значениями:
float a = 7., b = 4.4;
float result;
result = a + b; // Присвоится 11.4
result = a - b; // Присвоится 2.6
result = a * b; // Присвоится 30.800001
// Почему 30.800001, а не 30.8? Потому что вычисления с float обладают точностью до определённого
// знака -- дальше этого знака может начаться безумие. Так происходит из-за особенности хранения
// вещественных чисел в памяти. Если использовать double вместо float, то точность повысится и
// возрастёт до более дальнего знака после запятой.
result = a / b; // Присвоится 1.590909
result = a % b; // !!! ОШИБКА, операция "%" не может использоваться с вещественными числами !!!
Обрати внимание, что оператор % не может использоваться с вещественнымим числами.
Со смешанными значениями
Окей, операции отдельно с целыми, отдельно с вещественными значениями понятны – а что если смешивать целые и вещественные в одной операции?
В этом случае, результат будет превращаться в вещественный:
int a = 5;
float b = 4.5;
float floatResult = a + b; // Присвоится 9.5
// Присвоится 9 потому что результат 9.5 засовывается в
// целочисленную переменную, и дробная часть отбрасывается
int intResult = a + b;
// Это справедливо и для всех остальных операций: - * /
С приведением типа
В некоторых случаях может получиться так, у тебя на руках есть только целочисленные переменные, но тебе нужно их поделить друг на друга, и получить вещественный результат. Вот пример ситуации:
int a, b;
float result;
scanf("%d", &a); // Ввёл 6
scanf("%d", &b); // Ввёл 4
// Целочисленный результат 1 запишется в вещественную переменную,
// из-за чего целочисленное значение неявно приведётся к вещественное 1.000000
result = a / b;
print("%f\n", result); // Выведет 1.000000
Обрати внимание, что с этом случае мы записали целочисленное значение в вещественную переменную. В этом случае целочисленное значение неявно приводится к вещественному.
Что я могу сделать, чтобы получился правильный результат деления 1.5?
Для этого существует операция явного приведения типа – с её помощью можно прямо в выражении изменить тип значения переменной. Вот как это выглядит:
int a, b;
float result;
scanf("%d", &a);
scanf("%d", &b);
// Можно приводить к типу не только делимое, но и вообще любую переменную или число в выражении,
// и не только к double, но вообще к любому типу.
result = (double) a / b;
print("%f\n", result);
В этом случае выведется 1.500000, так как одна из переменных становится вещественной, а как мы знаем из предыдущего раздела “Со смешанными значениями” – “результат будет превращаться в вещественный”.
Я показал самый полезный случай использования приведения типа, но могут быть и какие-то другие экзотические случаи.
С операцией присваивания
Бинарные операторы можно красиво объединять с операцией присваивания:
int a = 3;
// Вот эта запись:
a = a + 10;
// Равноценна такой:
a += 10;
// Это справедливо для всех остальных операций: -= *= /= %=
Для злодеев
Просто чтоб ты знал – существует вариант использования присваивания с операторами для злодеев, который не надо использовать (но так можно):
int a = 2, b = 3, c = 4, d = 5;
a += (b += 5) * (c = 10) + d;
// Перепишу то же самое, но не по-злодейски:
b = b + 5; // Сначала выполняем первую скобку
c = 10; // Потом вторую
a = a + b * c + d; // Потом подставляем переменные в исходное выражение
Задание на закрепление
Я пока что дам пару простеньких заданий чтобы размять пальцы. Выдумывать какие-то сложные уравнения я не буду – просто если у тебя в будущем возникнет необходимость посчитать что-то сложное, то ты просто вернись к этом материалу. Через пару-тройку раз оно само засядет в подкорке.
Задания:
- Напиши программу, которая принимает с клавиатуры (scanf) номер студента, и выводит (printf) номер его варианта. Всего вариантов от 0 до 14. Например, если у студента номер 0 или 15, то у него будет вариант 0. Если у студента номер 2 или 17, то вариант 2. Подсказка: %
- Напиши программу, которая принимает с клавиатуры три вещественных числа, и выводит сумму двух первых чисел, умноженную на третье.
Унарные операторы
Раньше вы их скорее не встречали, так как они используются только в программированнии:
- Инкремент (увеличивает значение переменной на 1): ++
- Декремент (уменьшает значение переменной на 1): –
Вот так они используются:
int x = 5;
x++; // После этого x станет равен 6
x--; // А теперь x снова равен 5
С этими операторами есть хитрый момент – тут важно с какой стороны стоит оператор. Если оператор стоит:
- Слева – операция происходит до получения значения переменной
- Справа – операция происходит после получения значения переменной
Проще показать на примере:
int x, result;
x = 3;
// После этой строчки result станет равен 3, а x равен 4:
// то есть мы сначала выполнили операцию присваивания, а потом сделали инкремент переменной x
result = x++;
// Сбраcываем значение x на 3
x = 3;
// После этой строчки result равен 4, а равен 4:
// то есть мы сначала сделали инкремент, а потом выполнили операцию присваивания
result = ++x;
// Сбраcываем значение x на 3
x = 3;
// После этой строчки result равен 8, а x равен 4:
// то есть мы сначала выполнили операцию сложения, а потом сделали инкремент
result = x++ + 5;
// Сбраcываем значение x на 3
x = 3;
// После этой строчки result равен 9, а x равен 4:
// то есть мы сначала сделали инкремент, а потом выполнили операцию присваивания
result = ++x + 5;
Заключение
Итого, ты изучил:
- Бинарные операторы
- С целочисленными значениями
- С вещественными значениями
- Со смешанными значениями
- С приведением типа
- С операцией присваивания
- Для злодеев
- Унарные операторы
Если что – пиши, я помогу и постараюсь объяснить лучше.
Дальше на очереди – условия.