Из предыдущих статей вы узнали о различных концепциях C++, таких как: переменные, классы хранения, квалификаторы типов и т. д.. Вы также узнали, как можно изменить эти переменные.
Но чтобы выполнить эти модификации, нужно выполнить операции с этими переменными и константами, и для выполнения этих операций мы используем операторы.
Операторы — это символы, которые воздействуют на переменные или другие объекты, называемые операндами, и выполняют математические или логические операции для изменения их значений и получения соответствующих результатов.
Операторы в С++
Операторы составляют основу любого языка программирования. Без операторов мы не можем изменять или манипулировать объектами языков программирования и, следовательно, не можем получать желаемые результаты. C++ очень богат встроенными операторами, которые мы подробно обсудим далее в этой статье.
В C++ большинство операторов являются бинарными, т.е. эти операторы требуют двух операндов для выполнения операции. Некоторые операторы, такие как оператор ++ (инкремент), являются унарными операторами, что означает, что они работают только с одним операндом.
Существует также тернарный оператор в C++, называемый условным оператором, который принимает три операнда. Об этом вы узнаете более подробно в следующей части статьи.
Типы операторов в C++
Операторы в C++ классифицируются следующим образом:
Давайте подробно рассмотрим каждый тип оператора C++.
Арифметические операторы
Арифметические операторы используются для выполнения основных математических операций над операндами.
C++ поддерживает следующие арифметические операции:
Оператор | Двоичный/унарный | Описание |
---|---|---|
+ | Бинарный | Сложение двух операндов |
— | Бинарный | Вычитание двух операндов |
* | Бинарный | Умножение двух операндов |
/ | Бинарный | Деление двух операндов |
% | Бинарный | Оператор модуля — результат — остаток от деления |
++ | Унарный | Оператор инкремента — увеличивает значение операнда на 1 |
— | Унарный | Оператор декремента — уменьшает значение операнда на 1 |
В приведенном ниже примере демонстрируются первые пять арифметических операторов в C++:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
#include <iostream> #include <string> using namespace std; int main() { int op1=3,op2=4; float op3=10.1,op4=5.4; cout<<"Operands are op1 = "<<op1<<" op2 = "<<op2; cout<<" op3 = "<<op3<<" op4 = "<<op4; cout<<endl; cout<<"op1 + op2 = "<<op1+op2<<endl; cout<<"op1 - op2 = "<<op1-op2<<endl; cout<<"op3 * op4 = "<<op3*op4<<endl; cout<<"op3 / op4 = "<<op3/op4<<endl; cout<<"op2 % op1 = "<<op2%op1<<endl; } |
Вывод данных:
Операнды: op1 = 3 op2 = 4 op3 = 10.1 op4 = 5.4
op1 + op2 = 7
op1 – op2 = -1
op3 * op4 = 54.54
op3 / op4 = 1.87037
Программа сначала определяет операнды, а затем выполняет арифметические операции над этими операндами. Эта программа демонстрирует использование арифметических операторов в C++.
Следующие арифметические операторы, которые мы собираемся обсудить, это ++ и –. Они называются операторами инкремента и декремента соответственно. Оператор инкремента увеличивает значение операнда на 1, а оператор декремента уменьшает значение операнда на 1.
Выражение x++ эквивалентно:
х+=1;
х = х+1;
Точно так же выражение x—эквивалентно
х-=1;
х = х-1;
Операторы инкремента и декремента могут быть помещены как префикс, так и суффикс операнда. В зависимости от своего размещения эти операторы имеют разное значение для вычисления выражения.
При размещении в качестве префикса операция увеличения/уменьшения известна как предварительное увеличение или предварительное уменьшение соответственно. При размещении в виде суффикса операция увеличения/уменьшения называется соответственно операцией преинкремента или постдекремента.
Всякий раз, когда задействованы выражения, в случае предварительного увеличения или предварительного уменьшения, сначала выполняется операция (увеличение или уменьшение), а затем выполняется присваивание. В случае преинкремента или постдекремента сначала выполняется присваивание, а после этого выполняется операция.
Мы можем лучше понять это, используя следующий пример:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
#include <iostream> #include <string> using namespace std; int main() { int x=4,y; y = ++x; cout<<"PreIncrement:Value of x = "<<x; cout<<endl; cout<<"PreIncrement:Value of y = "<<y; cout<<endl; y = x--; cout<<"PostDecrement:Value of x = "<<x; cout<<endl; cout<<"PostDecrement:Value of y = "<<y; cout<<endl; } |
Вывод данных:
Преинкрементное значение x = 5
Преинкрементное значение y = 5
Постдекрементное значение x = 4
Постдекрементное значение y = 5
Это программа для демонстрации операций увеличения и уменьшения. Обратите внимание, что в этой программе мы использовали операторы преинкремента и постдекремента. Для первого выражения y=++x, поскольку это предварительное приращение, сначала будет увеличено значение x, а затем результирующее значение будет присвоено y. Это видно из того, что мы получили.
Во втором выражении y=x– значение x, которое теперь равно 5, будет сначала присвоено y, а затем значение x будет уменьшено. Следовательно, в выводе мы видим, что для операции постдекремента значение y равно 5, а x равно 4.
Логические операторы
Логические операторы используются для оценки комбинации условий/ограничений для получения результирующего значения. Результатом вычисления логического выражения является логическое значение, которое либо истинно, либо ложно.
C++ поддерживает следующие логические операторы:
Оператор | Описание |
---|---|
&& | Логическое И: возвращает true (истину), если оба условия истинны, в противном случае возвращает false (ложь). |
|| | Логическое ИЛИ: возвращает true, если одно из условий истинно. Возвращает false, если оба условия ложны. |
! | Логическое НЕ: отрицает условие. |
C++ использует метод короткого замыкания для вычисления логических выражений. При этом C++ должен оценить только первое выражение/операнд логического выражения, чтобы предоставить результат. Например, для логического оператора AND (&&) C++ оценивает только первое выражение. Если оно ложно, то результат будет ложным, даже если второе условие истинно.
Аналогично, для логического OR (||) оценивается только первое выражение. Если первое выражение истинно, то и результат будет истинным, поэтому второе выражение вычислять не нужно.
Ниже приведен пример, показывающий использование логических операторов:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
#include <iostream> #include <string> using namespace std; int main() { int a=10, b=8,c=12,d=14; if(!(a==0)) cout<<"a is not zero"<<endl; else cout<<"a is zero"<<endl; if((a>b)&&(c<d)) cout<<"Logical AND is true"<<endl; else cout<<"Logical AND is false"<<endl; if((a<c)||(b<d)) cout<<"Logical OR is true"<<endl; else cout<<"Logical OR is false"<<endl; } |
Вывод данных:
a не равно нулю
Логическое И истинно
Логическое ИЛИ истинно
В приведенной выше программе мы использовали все три логических оператора для вычисления выражений и вывода результатов.
Реляционные операторы
Операторы отношения или сравнения используются для сравнения двух операндов. Результат оценки либо истина, либо ложь.
C++ поддерживает следующие операторы отношения:
Оператор | Описание |
---|---|
!ERROR! unexpected operator ‘=’ | Проверяет, равны ли два операнда. Возвращает true, если равно, иначе возвращает false. |
!=(not equal to) | Дополняет оператор «равно». Возвращает true, если операнды не равны. |
<(less than) | Возвращает true, если первый операнд меньше второго. |
<=(less than equal to) | Возвращает true, если первый операнд меньше или равен второму операнду. |
>(greater than) | Возвращает true, если первый операнд больше второго. |
>=(greater than equal to) | Возвращает true, если первый операнд больше второго. |
Пример программы для понимания операторов отношения:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
#include <iostream> #include <string> using namespace std; int main() { int a=10, b=8,c=12,d=14; if(a==b) cout<<"a is equal to b"<<endl; else cout<<"a is not equal to b"<<endl; if(c!=d) cout<<"c is not equal to d"<<endl; else cout<<"c is equal to d"<<endl; if((a+b) <= (c+d)) cout<<" (a+b) less than/equal to (c+d)"<<endl; if((a-b)>=(d-c)) cout<<"(a-b) greater than/equal to (d-c)"<<endl; } |
Вывод данных:
a не равно b
c не равно d
(a+b) меньше/равно (c+d)
(ab) больше/равно (dc)
В приведенной выше программе мы видим использование операторов отношения и то, как они оценивают предоставленные выражения.
Обратите внимание, что мы можем предоставлять не только значения, но также переменные и выражения в условных операторах.
Побитовые операторы
Побитовые операторы в C++ работают с битами предоставленных операндов. Побитовые операторы применяются только к целочисленным типам, таким как целое число, символ и т. д., а не к типам данных, таким как float, double и т. д.
Ниже приведены побитовые операторы, поддерживаемые C++:
Операторы | Описание |
---|---|
& (Двоичное AND) | Выполняет операцию И над битами операнда 1 и операнда 2. |
| (Двоичное OR) | Выполняет операцию ИЛИ над битами операнда 1 и операнда 2. |
^ (Двоичный XOR) | Выполняет операцию XOR над битами операнда 1 и операнда 2. |
~ (бинарное дополнение) | Берет один операнд и инвертирует его биты. |
<< ( Двоичный оператор сдвига влево) | Сдвигает биты первого операнда влево на число битов, указанное вторым операндом. |
>> (Двоичный оператор сдвига вправо) | Сдвигает биты первого операнда вправо на количество позиций, указанное вторым операндом. |
Эти побитовые операторы работают с операндами побитно. Таблицы истинности для операций AND, OR и XOR приведены ниже.
Рассмотрим a и b как два бита, над которыми должны выполняться операции AND, OR и XOR.
Таблицы истинности для них приведены ниже:
a | b | a&b | a|b | a^b |
---|---|---|---|---|
0 | 0 | 0 | 0 | 0 |
1 | 0 | 0 | 1 | 1 |
0 | 1 | 0 | 1 | 1 |
1 | 1 | 1 | 1 | 0 |
Давайте разберем пример, для понимания побитовых операций.
Пусть a=8 и b=4
Двоичное представление a и b выглядит следующим образом:
а=8 1000
а=4 0100
a&b 0000 = 0
a|b 1100 = 12
a^b 1100 = 12
В приведенном выше примере мы видим, что побитовое И (AND) для 8 и 4 равно 0. Побитовое ИЛИ (OR) для 8 и 4 равно 12, а побитовое XOR для 8 и 4 также равно 12.
Это способ, которым побитовые операции выполняются побитовыми операторами.
Пример, демонстрирующий работу побитовых операторов:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
#include <iostream> #include <string> using namespace std; int main() { int a=8,b=4,c; c = a&b; cout<<"Result of & : "<<c<<endl; c = a|b; cout<<"Result of | : "<<c<<endl; c = a^b; cout<<"Result of ^ : "<<c<<endl; c = a<<2; cout<<"Result of << by 2 bits : "<<c<<endl; c = b>>2; cout<<"Result of >> by 2 bits : "<<c<<endl; c = ~3; cout<<"Result of ~ : "<<c<<endl; } |
Вывод данных:
Результат & : 0
Результат | : 12
Результат ^ : 12
Результат << на 2 бита: 32
Результат >> на 2 бита: 1
Результат ~ : -4
В приведенной выше программе мы продемонстрировали использование побитовых операторов, а также написали вывод каждой операции.
Операторы присваивания
Оператор присваивания «=» используется для присвоения значения переменной. Левая часть оператора присваивания — это переменная, а правая часть — это значение, которое должно быть присвоено этой переменной. Значение в правой части должно быть того же типа, что и переменная в левой части.
Обратите внимание на разницу между операторами ‘=’ и ‘==’. Первый является оператором присваивания, а второй — оператором равенства.
Операция присваивания происходит справа налево. Помимо оператора присваивания ‘=’, существуют и другие варианты оператора присваивания, известные как «составные операторы присваивания». Эти операторы выполняют операцию в дополнение к присваиванию.
В таблице ниже дано описание этих операторов присваивания:
Оператор | Описание |
---|---|
= | Присваивает значение правого операнда левому операнду |
+= | Добавляет правый операнд к левому операнду и присваивает результат левому операнду. |
-= | Вычитает правый операнд из левого операнда и присваивает результат левому операнду |
*= | Умножает правый операнд на левый операнд и присваивает результат левому операнду |
/= | Делит правый операнд на левый операнд и присваивает результат левому операнду |
Как показано в приведенной выше таблице, если x и y являются операндами, x+=y эквивалентно x = x+y.
Получается,
x -=y эквивалентно x = xy.
x *= y эквивалентно x = x*y.
x /= y эквивалентно x = x/y.
Приведенный ниже пример демонстрирует работу операторов присваивания:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
#include <iostream> #include <string> using namespace std; int main() { int x,y; cout<<"Enter input variable y: "; cin>>y; x = y; cout<<"\nValue of x = "<<x<<endl; int a = 3,b = 5,c = 8; a += b; c -= b; cout<<"\na += b: "<<a; cout<<"\nc -= b: "<<c; a *= b; b /= c; cout<<"\na *= b: "<<a; cout<<"\nb /= c: "<<b; return 0; } |
Вывод данных:
Входная переменная y: 4
Значение х = 4
a += b : 8
c -= b : 3
a *= b : 40
b /= c : 1
В приведенном выше примере мы продемонстрировали присваивание, а также составные операторы присваивания.
Вы также можете комбинировать другие бинарные операторы, такие как %, <<, >>, &, |, ^ и т. д., в составные операторы присваивания в дополнение к уже продемонстрированным.
Другие операторы
До сих пор мы использовали только основные операторы C++, но есть еще несколько дополнительных операторов C++, которые требуют нашего внимания.
К таким операторам относятся:
оператор sizeof
sizeof — это унарный оператор, который широко используется в C и C++. Sizeof возвращает размер своего операнда. Возвращаемое значение обычно представляет собой целочисленный тип без знака, обозначаемый ‘size_t’.
Оператор Sizeof широко используется в языках C и C++. Его можно использовать для определения размера переменных, массивов или выражений и даже для выделения блоков памяти.
Условный тернарный оператор
Условный оператор в C++ можно использовать вместо оператора if-else.
Общий синтаксис условного оператора:
1 |
Condition? expression1:expression2; |
Если условие истинно, будет оцениваться выражение 1. Если условие ложно, то будет оцениваться выражение2.
Обратите внимание, что выражение1 и выражение2 должны иметь одинаковые типы данных, чтобы избежать возможных ошибок.
Оператор запятой
Оператор запятой, представленный токеном ‘,’, может использоваться как оператор, а также как разделитель.
В качестве оператора запятая используется, когда необходимо оценить более одного выражения. Только самое правое выражение присваивается левому операнду.
Например, рассмотрим следующее выражение:
х = (у=4, у+1);
В этом выражении у нас есть два выражения справа, разделенные запятой. Здесь запятая выступает в роли оператора. Сначала будет вычислено выражение y=4. Затем следующее выражение y+1 будет оцениваться с использованием результата первого выражения, т.е. y=4. Таким образом, значение y+1 будет равно 5, и это значение будет присвоено x.
В качестве разделителя запятая может использоваться в любом месте для разделения определений, списка параметров и т. д.
Оператор доступа к членам
Есть два оператора, которые используются для доступа к отдельным членам классов, структур или объединений в C++. Это оператор точки (.) и оператор стрелки (->).
В приведенном ниже примере показано использование sizeof, запятой и условного оператора.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
#include <iostream> #include <string> using namespace std; int main() { int x,y; x = (y=3,y+4); cout<<"Value of x = "<<x; y = (x<5)?0:1; if(y == 0) cout<<"\nVariable x is less than 5"<<endl; else cout<<"\nVariable x is greater than 5"<<endl; cout<<"sizeof(x): "<<sizeof(x)<<"\t"<<"sizeof(y): "<<sizeof(y); return 0; } |
Вывод данных:
Значение x = 7
Переменная x больше 5
sizeof(x): 4 sizeof(y): 4
Скриншот вывода данных:
Как показано в приведенной выше программе, сначала у нас есть две объявленные переменные, разделенные запятой. (запятая как разделитель). Далее у нас есть оператор запятой с двумя выражениями. Как видно из вывода, самое правое значение выражения присваивается переменной x. Далее мы демонстрируем условный оператор для оценки того, меньше ли x 5.
Наконец, мы демонстрируем использование оператора sizeof. Здесь мы используем оператор sizeof, чтобы получить размер переменных x и y. Поскольку обе переменные являются целочисленными, возвращаемый размер равен 4 байтам.
Приоритет операторов и ассоциативность
Вы уже видели почти все операторы C++ и знаете, что их можно использовать в выражениях для выполнения определенных операций. Но выражения, которые вы видели в примерах, просты и понятны. Однако, в зависимости от наших требований, выражения становятся все более и более сложными.
Такие сложные выражения будут иметь более одного оператора и множество операндов. В такой ситуации вам нужно оценить, какой оператор должен быть оценен первым.
Например , рассмотрим следующее выражение.
х = 4 + 5/3;
Здесь у нас есть операторы + и /, и нам нужно решить, какое выражение будет оцениваться первым. Говоря математическим языком, мы знаем, что деление будет выполняться перед сложением. Таким образом, выражение примет вид x = 4 + (5/3) = 5.
Но когда компилятор сталкивается с такой ситуацией, нам также нужен аналогичный механизм для определения порядка операций, чтобы он мог правильно вычислить выражение.
Этот порядок, в котором оцениваются операторы в составном выражении, называется «приоритетом» оператора. C++ определил приоритет для всех операторов, и операторы с более высоким приоритетом оцениваются первыми.
Что происходит, когда у нас есть два оператора рядом в выражении с одинаковым приоритетом? Здесь на сцену выходит ассоциативность оператора.
Ассоциативность сообщает компилятору, следует ли оценивать выражение в последовательности слева направо или справа налево. Таким образом, используя приоритет и ассоциативность оператора, мы можем эффективно вычислить выражение и получить желаемый результат.
C++ предоставляет таблицу, состоящую из приоритета и ассоциативности различных используемых им операторов:
Приоритет/ассоциативность | Оператор | Описание |
---|---|---|
1 None | :: :: |
Оператор разрешения области видимости (унарный) (бинарный) |
2 L->R | () () () {} type() type{} [] . -> ++ –– typeid const_cast dynamic_cast reinterpret_cast static_cast |
Круглые скобки Вызов функции Инициализация Единая инициализация (C++11) Функциональное приведение Функциональное приведение (C++11) Нижний индекс массива Доступ к члену из объекта Доступ к члену из объекта ptr Постинкремент Постдекремент Информация о типе времени выполнения Отбрасывание const Run- приведение типа с проверкой типа во время Приведение одного типа к другому Приведение с проверкой типа во время компиляции |
3 R->L | + — ++ –– ! ~ (type) sizeof & * new new[] delete delete[] |
Унарный плюс Унарный минус Преинкремент Предекремент Логическое НЕ Побитовое НЕ приведение в стиле C Размер в байтах Адрес разыменования Динамическое выделение памяти Динамическое выделение массива Динамическое удаление памяти Динамическое удаление массива |
4 L->R | ->* .* |
Селектор указателя на элемент Селектор объекта-члена |
5 L->R | * / % |
Модуль Деление Умножение |
6 L->R | + — |
Сложение Вычитание |
7 L->R | << >> |
Побитовый сдвиг влево Побитовый сдвиг вправо |
8 L->R | < <= > >= |
Сравнение меньше, чем Сравнение меньше или равно Сравнение больше, чем Сравнение больше или равно |
9 L->R | !ERROR! illegal character ‘!’ |
Равенство Неравенство |
10 L->R | & | Побитовое И (AND) |
11 L->R | ^ | Побитовое XOR |
12 L->R | | | Побитовое ИЛИ (OR) |
13 L->R | && | Логическое AND |
14 L->R | || | Логическое OR |
15 R->L | ?: = *= /= %= += -= <<= >>= &= |= ^= |
Условное (см. примечание ниже) Назначение Назначение умножения Назначение деления Назначение модуля Назначение сложения Назначение вычитания Побитовый сдвиг влево Назначение побитового сдвига вправо Назначение побитового AND Побитовое назначение OR Побитовое назначение XOR |
16 R->L | throw | Сбросить выражение |
17 L->R | , | Оператор запятой |
Кстати:
- Уровень приоритета 1 — это самый высокий уровень приоритета, а уровень 17 — самый низкий. Операторы с более высоким уровнем приоритета оцениваются первыми.
- L->R означает ассоциативность слева направо.
- R->L означает ассоциативность справа налево.
Вывод
На этом наша статья об операторах в C++ заканчивается. Мы обсудили почти всех операторов. Некоторые конкретные операторы, присутствующие в приведенной выше таблице приоритетов, которые мы не обсуждали, будут обсуждаться в соответствии с темами, которые мы рассмотрим в дальнейшем. А в следующей статье мы с вами поговорим о роль и важности конструкций принятия решений в C++.
С Уважением, МониторБанк