Над переменными и литералами мы можем выполнять различные операции.
Базовые математические операции
Начнём с операции сложения, она выглядит так же как и в математике:
int a = 1;
int b = 2;
int c = a + b;
std::cout << c << std::endl;
3
То же самое касается остальных арифметических операций:
int a = 6;
int b = 2;
std::cout << (a + b) << std::endl;
std::cout << (a - b) << std::endl;
std::cout << (a / b) << std::endl;
std::cout << (a * b) << std::endl;
8
4
3
12
Особенности операции сложения
При сложении двух переменных типа char мы выполняем операцию не над символами, а над их числовым представлением:
char a = 'A';
char b = 'B';
std::cout << a << std::endl;
std::cout << b << std::endl;
std::cout << (int)a << std::endl;
std::cout << (int)b << std::endl;
std::cout << (char)(a+b) << std::endl;
std::cout << (int)(a+b) << std::endl;
A
B
65
66
â
131
Стоит отметить что значение символа â с кодом 131 не гарантированно в этом случае, и зависит от многих факторов таких как кодировка, платформа и знаковость типа char.
При выполнении операции выполняется целочисленное продвижение (integer promotion) или же расширение типа.
Это означает что значения типа char (или других более узких типов - short, bool) неявно преобразуются в значения более широких типов - обычно int или unsigned int, если тип int не способен представить значение.
Типы, которые подвержены целочисленному продвижению: char, signed char, unsigned char, bool, short, unsigned short.
Этот механизм используется в C++ для обеспечения корректности математических операций.
Операция унарного минуса
При такой записи
int x = -5;
знак минус здесь - это оператор унарного минуса, применяемый к литералу 5.
Сначала создаётся литерал 5, затем к нему применяется оператор унарного минуса, который меняет знак значения.
Нужно отметить что это происходит не во время выполнения, а во время компиляции.
В этом вы можете убедиться если напишете эту строчку кода и наведёте курсор на значение -5.
Вы увидите (int)5, это зависит от IDE, но в VS это отображается именно так.
Особенности операции деления
Нужно отметить, что если мы поделим два числа типа int со значениями 1 и 2 то мы получим 0.
int a = 1;
int b = 2;
std::cout << (a / b) << std::endl;
0
Это происходит не потому, что целочисленный тип int не имеет возможности хранить дробную часть, а потому что такая операция изначально выполняется как целочисленное деление из-за типа литералов.
Если нас это не устраивает и нам дробная часть нужна - необходимо использовать тип, который это делать позволяет, допустим, тип float:
float a = 1;
float b = 2;
std::cout << (a / b) << std::endl;
0.5
Допустим, если мы поделим 5 на 2 мы получим 2 при использовании типа int.
int a = 5;
int b = 2;
std::cout << (a / b) << std::endl;
2
То есть эта особенность не запрещает нам делить целочисленные типы между собой, но накладывает такого рода ограничения.
Если мы применим операцию деления таким образом:
double x = 7 / 2;
std::cout << x << std::endl;
3
То мы получим неожиданный результат.
Это происходит потому, что сначала выполняется целочисленное деление, а потом его результат конвертируется в double.
double x = 7.0 / 2;
double y = 7.f / 2;
std::cout << x << std::endl;
std::cout << y << std::endl;
3.5
3.5
Для того чтобы эта логика работала так, как мы ожидаем - необходимо, чтобы хотя бы один из литералов имел тип числа с плавающей точкой.
Необходимо это указать явно.
Операция взятия остатка от деления
Отдельно стоит выделить оператор % он позволяет выполнить операцию взятия остатка от деления
int a = 5;
int b = 2;
std::cout << (a % b) << std::endl;
1
Эта операция не часто встречается в привычной математике, но в программировании она бывает очень полезной.
Мы можем применять оператор получения остатка от деления только к целым типам.
Оформите подписку, чтобы иметь доступ ко всем публикациям без ограничений. Вы получите мгновенный доступ к полным версиям материалов, исходному коду и новым публикациям сразу после их выхода.
Я регулярно публикую материал и разборы ситуаций для различных игр, движков, а так же подходов разработки включая Internal, External и DMA.