PVOID - Операторы

Операторы

Этот раздел является переводом туториала C++ Language


   После введения в переменные и константы, мы можем начинать работать с ними при помощи операторов. Ниже приведен полный список операторов. На данный момент, вполне вероятно, не обязательно знать их все, но они все перечислены здесь в качестве ссылки.

Оператор присваивания (=)


   Оператор присваивания присваивает значение переменной.

x = 5;

   Это выражение присваивает целочисленное значение 5 переменной x. Операция присваивания всегда производится справа налево, а не наоборот:

x = y;

   Это выражение присваивает переменной x значение, содержащееся в переменной y. Значение x в момент перемещения теряется и замещается значением y.

   Учтите, что мы присваиваем значение y переменной x только в момент операции присваивания. Поэтому, если y изменится позже, это не повлияет на новые значения, принятые x.

Например, давайте взглянем на следующий код - в нем содержится эволюция данных, хранящихся в переменных, аналогично комментариям:

// оператор присваивания
#include <iostream>
using namespace std;

int main ()
{
  int a, b;         // a:?,  b:?
  a = 10;           // a:10, b:?
  b = 4;            // a:10, b:4
  a = b;            // a:4,  b:4
  b = 7;            // a:4,  b:7

  cout << "a:";
  cout << a;
  cout << " b:";
  cout << b;
}
a:4 b:7

 

Эта программа выводит на экран последние значения a и b (4 и 7, соответственно). Заметьте, что последняя модификация b не повлияла на a, хотя мы объявили a = b ранее.

Операции присваивания - это выражения, которые могут быть вычислены. Это означает, что присваивание само по себе имеет значение, и для фундаментальных типов это значение, присваиваемое в операции. Например:

y = 2 + (x = 5);

   В этом выражении переменной y присваивается результат сложения 2 и значение другой операции присваивания (собственное значение которой 5). Это примерно эквивалентно:

x = 5;
y = 2 + x;

   С финальным результатом присваивания 7 переменной y.

Следующее выражение также корректно в C++:

x = y = z = 5;

Здесь присваивается 5 всем трем переменным: x, y и z; всегда справа-налево.

 

Арифметические операторы ( +,-,*,/,% )


C++ поддерживаются пять арифметических операций:

 оператор   описание
 +  сложение
 -  вычитание
 *  умножение
 /  деление
 %  модуль

 

   Операции сложения, вычитания, деления и умножения соответствуют буквально их соответствующим математическим операторам. Последний, оператор модуля, представляемый знаком процента (%), дает остаток от деления двух значений. Например:

x = 11 % 3;

 в результате в переменной x содержится значение 2, т.к результат деления от 11 на 3 равен 3 с остатком 2.

 

Составное присваивание (+=, -=, *=, /=, %=, >>=, <<=, &=, ^=, |=)


   Составные операторы присваивания изменяют текущее значение переменной, производя операцию над ней. Они эквивалентны присваиванию результата операции первому операнду:

 выражение   эквивалент 
 y += x;  y = y + x;
 x -= 5;  x = x - 5;
 x /= y;  x = x / y; 
 price *= units +1;   price = price * (units+1); 

 

 и то же самое для всех остальных составных операторов присваивания. Например:

// составные операторы присваивания
#include <iostream>
using namespace std;

int main ()
{
  int a, b=3;
  a = b;
  a+=2;             // эквивалентно a=a+2
  cout << a;
}
5

 

Инкремент и декремент ( ++, -- )


   Многие выражения могут быть сильно сокращены: операторы инкремента (++) и декремента (--) увеличивают или уменьшают на 1 значение, хранимое в переменной. Они эквивалентны +=1 и -=1 соответственно.

++x;
x+=1;
x=x+1;

   Три эти выражения полностью эквивалентны в своей функциональности; каждое из них увеличивает на единицу значение x.

Ранние компиляторы C могли создавать различный исполняемый код в зависимости от того, какое из этих выражений используется. В наше время этот вид оптимизации кода обычно выполняется автоматически компилятором, таким образом, эти три выражения должны произвести точно такой же исполняемый код.

Особенностью этого оператора является то, что он может использоваться как префикс и как суффикс. Это означает, что оно может быть написано как перед именем переменной (++x), так и после него (x++). Несмотря на то, что в простых выражениях как x++ или ++x они равнозначны, в других выражениях, в которых результат инкремента или декремента используется, они могут иметь важный различия в значении: в случае, когда оператор инкремента используется как префикс (++x) значения, выражение принимает конечное значение уже после того, как операция инкремента совершена. С другой стороны, в случае, когда он используется как суффикс (x++), значение x также увеличится, но выражение примет значение прежде, чем это произойдет. Заметьте разницу:

 Пример 1   Пример 2 
 x = 3;
 y = ++x;
 // x содержит 4, y содержит 4 
 x = 3;
 y = x++;
 // x содержит 4, y содержит 3 

 В Примере 1 значение, присваиваемое y, это значение x после инкремента, в то время как в Примере 2 это значение, которое содержалось в x до инкремента.

 Операторы отношения и сравнения ( ==, !=, >, <, >=, <= )


   Два выражения можно сравнить с использованием операторов отношения или равенства. Например, чтобы узнать, что два значения равны или одно больше другого.

Результат такой операции может принимать значение true или false (т.е. Булево значение).

Операции отношения в C++ это:

 оператор   описание 
 ==  равно
 !=  не равно
 <  меньше
 >  больше
 <=  меньше или равно 
 >=  больше или равно

   Здесь представлены некоторые примеры:

(7 == 5)     // false
(5 > 4)      // true
(3 != 2)     // true
(6 >= 6)     // true
(5 < 5)      // false

   Конечно, сравнивать можно не только числовые константы, но и другие значения, включая переменные.

Предположим, что a=2, b=3 и c=6, тогда:

(a == 5)     // false, т.к. a не равно 5
(a*b >= c)   // true, т.к. (2*3 >= 6) истинно
(b+4 > a*c)  // false, т.к. (3+4 > 2*6) ложно
((b=2) == a) // true 

   Будьте осторожны! Оператор присваивания (operator=, с одним знаком =) это не то же самое, что оператор равенства (operator==, с двумя знаками =); первый из них (=) присваивает значение, стоящее справа от него переменной, находящейся слева, в то время как другой (==) сравнивает значения с двух сторон оператора на равенство. Поэтому в последнем выражении ((b=2) == a), мы сначала присвоили значение 2 переменной b, а затем сравнили его с a, которая также содержала значение 2, и получили true.

 

Логические операторы ( !, &&, || )


   Оператор ! - это оператор C++ для логической операции НЕ. Он имеет только один операнд справа, и инвертирует его, возвращая false, если его операнд имеет значение true и наоборот. Он возвращает противоположное логическое значение своего операнда. Например:

!(5 == 5)   // возвращает false т.к. выражение справа (5 == 5) будет true
!(6 <= 4)   // возвращает true т.к. (6 <= 4) будет false
!true       // возвращает false
!false      // возвращает true

   Логические операторы && и || используются при оценке двух выражений для получения результата, зависящего от значений этих выражений. Оператор && соответствует логической операции И, которая возвращает значение true, если оба его операнда истинны, и false в противном случае. В таблице показан результат применения оператора &&:

 ОПЕРАТОР && (И) 
a b a && b
 true  true  true
 true  false  false
 false  true  false
 false  false  false

 

   Оператор || соответствует логической операции ИЛИ, которая возвращает true, если любой из ее операндов равен true, поэтому принимает значение false, только если оба операнда равны false. Ниже приведена таблица для a || b:

 ОПЕРАТОР || (ИЛИ) 
a b a || b
 true  true  true
 true  false  true
 false  true  true
 false  false  false

 

Пример:

( (5 == 5) && (3 > 6) )  // вернет false ( true && false )
( (5 == 5) || (3 > 6) )  // вернет to true ( true || false ) 

   При использовании логических операторов C++ оценивает только то, что необходимо, слева-направо для получения итогового результата, игнорируя остальное. Поэтому в последнем примере ((5==5)||(3>6)) C++ проверяет, истинно ли 5==5, и если это так, то значение 3>6 не проверяется. Это известно как укороченная оценка и для этих операторов работает так:

 

 оператор   укороченная оценка 
 &&  Если левостороннее выражение равно false, итоговый результат равен false (правостороннее выражение не оценивается)
 ||  Если левостороннее выражение равно true, итоговый результат равен true (правостороннее выражение не оценивается)

 

   Это особенно важно, когда правое выражение имеет побочные эффекты, такие как изменение значений:

if ( (i<10) && (++i<n) ) { /*...*/ } // Обратите внимание, что условие увеличивает i

   Здесь комбинированное условное выражение увеличивает i на единицу, но только если условие слева от && истинно, иначе условие справа (++ i <n) никогда не будет оцениваться.

 

Тернарный условный оператор ( ? )


   Условный оператор оценивает выражение, возвращая одно значение, если выражение истинно и другое значение, если выражение ложно. Его синтаксис:

condition ? result1 : result2

Если condition истинно, все выражение оценивается как result1, иначе как result2.

7==5 ? 4 : 3     // оценивается как 3, т.к. 7 не равно 5.
7==5+2 ? 4 : 3   // оценивается как 4, т.к. 7 равно 5+2.
5>3 ? a : b      // оценивается как значение a, т.к. 5 больше, чем 3.
a>b ? a : b      // оценивается в зависимости от значений a и b.

 

Пример:

// условный оператор
#include <iostream>
using namespace std;

int main ()
{
  int a,b,c;

  a=2;
  b=7;
  c = (a>b) ? a : b;

  cout << c << '\n';
}
7

   В этом примере, a равно 2, и b равно 7, так что оцениваемое выражение (a>b) не было истинным, таким образом, первое значение, указанное после вопросительного знака, было отброшено в пользу второго значения (указанного после двоеточия), которым является b (со значением 7).

 

Оператор запятая ( , )


  Оператор запятая (,) используется для разделения двух или более выражений, который включается, когда ожидается только одно выражение. Когда набор выражений оценивается для получения значения, рассматривается только самое правое выражение.

Например, следующий код:

a = (b=3, b+2);

   сначала присваивает значение 3 переменной b, а затем присваивает b + 2 переменной a. Таким образом, в конце переменная a будет содержать значение 5, а переменная b будет содержать значение 3.

 

Побитовые операторы ( & , | , ^ , ~ , << , >> )


   Побитовые операторы модифицируют переменные, учитывая битовые шаблоны, которые представлены значениями, хранимыми в этих переменных.

 оператор   эквивалент asm   описание 
 &  AND  побитовый И 
 |  OR  побитовый включающий ИЛИ 
 ^  XOR  побитовый исключающий ИЛИ 
 ~  NOT  унарное дополнение (битовая инверсия) 
 <<  SHL  сдвиг бит влево
 >>  SHR  сдвиг бит вправо

 

 Оператор явного приведения типа


   Операторы преобразования типов позволяют преобразовывать значение заданного типа в другой тип. Есть несколько способов сделать это на C ++. Самый простой, который был унаследован от языка C, это предварять выражение, которое должно быть преобразовано, новым типом, заключенным в круглые скобки (()):

int i;
float f = 3.14;
i = (int) f;

   Предыдущий код преобразует число с плавающей точкой 3.14 в целое значение (3); Остаток теряется. Здесь оператором приведения типа является (int). Еще один способ сделать то же самое в C ++ - использовать функциональную нотацию, предваряя выражение, которое нужно преобразовать, типом и заключая выражение в круглые скобки:

i = int (f);

   Оба способа приведения типов корректны в C++.

 

 sizeof


   Этот оператор принимает один параметр, который может быть типом или переменной, и возвращает размер в байтах этого типа или объекта:

x = sizeof (char);

   Здесь переменной x присваивается значение 1, потому что char - это тип  размером в один байт. Значение, возвращаемое sizeof, является константой времени компиляции, поэтому оно всегда определяется перед выполнением программы.

 

 Другие операторы


   Позже в этом руководстве мы увидим еще несколько операторов, подобных тем, которые относятся к указателям или специфике объектно-ориентированного программирования.

 

Приоритет операторов


 Одно выражение может иметь несколько операторов. Например:

x = 5 + 7 % 2;

   В C ++ вышеуказанное выражение всегда присваивает значение 6 переменной x, поскольку оператор % имеет более высокий приоритет, чем оператор +, и всегда вычисляется раньше. Части выражений могут быть заключены в круглые скобки, чтобы переопределить этот порядок приоритетов или явно очистить предполагаемый эффект. Обратите внимание на разницу:

x = 5 + (7 % 2);    // x = 6 (так же, как без скобок)
x = (5 + 7) % 2;    // x = 0 

 

Операторы C ++ оцениваются в следующем порядке от наивысшего к наименьшему:

 

 Уровень  Группа приоритетов  Оператор  Описание  Группировка
 1   область видимости  : :  Спецификатор области видимости  слева-направо
 2  Постфикс (унарный)  ++ --  постфиксный инкремент / декремент  слева-направо
 ()  функциональные формы  справа-налево
 []  индекс  слева-направо
 . ->  доступ к членам  слева-направо
 3   Префикс (унарный)  ++ --  префиксный инкремент / декремент  слева-направо
 ~ !  побитовое НЕ / логическое НЕ  слева-направо
 + -  унарный префикс  слева-направо
 & *  ссылка / разыменование  слева-направо
 new delete  выделение / освобождение памяти  слева-направо
 sizeof  число элементов в parameter pack  слева-направо
 (type)  приведение типов в стиле C  слева-направо
 4  Указатель на член  .*  ->*  доступ к члену  слева-направо
 5  Арифметические: умножение  * / %  умножение / деление /модуль  слева-направо
 6  Арифметические: сложение  + -  сложение / вычитание  слева-направо
 7  Побитовый сдвиг  << >>  сдвиг влево / сдвиг вправо  слева-направо
 8  Отношение  < > <= >=  операторы сравнения  слева-направо
 9  Равенство  == !=  равенство / неравенство  слева-направо
 10  И  &  побитовое И  слева-направо
 11  Исключающее ИЛИ  ^  побитовое исключающее ИЛИ  слева-направо
 12  Включающее ИЛИ  |  побитовое ИЛИ  слева-направо
 13  Конъюнкция  &&  логическое И  слева-направо
 14  Дизъюнкция  | |  логическое ИЛИ  слева-направо
 15  Присваивание   = *= /= %= += -=
 >>= <<= &= ^= |=
  присваивание / составное присваивание  справа-налево
 ? :  условный оператор
 16  Упорядочивание  ,  разделитель запятая  слева-направо

 

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

Заключение отдельных частей выражения в скобки (даже если в этом нет необхоимости) улучшает читаемость кода.