Если y==0
, то результат выражений x/y
и x%y
не определен. Если переменная x
или y
является отрицательной, то результат выражения x%y
является отрицательным.
Для встроенных типов операторы >>
и <<
означают сдвиг битов (см. раздел 25.5.4). Если левым операндом является объект класса iostream
, то эти операторы используются для ввода и вывода (см. главы 10-11).
Результатом оператора сравнения является значение типа bool
.
Обратите внимание на то, что x!=y
эквивалентно !(x==y)
. Результат оператора равенства имеет тип bool
.
Оператор &
(как и операторы ^
, |
, ~
, >>
и <<
) возвращает комбинацию битов. Например, если переменные a
и b
имеют тип unsigned char
, то результат выражения a&b
имеет тип unsigned char
, в котором каждый бит является результатом применения оператора &
к соответствующим битам переменных a
и b
(раздел A.5.5).
См. раздел А.5.5.
Рассмотрим пример.
template
Оператор “знак вопроса” описан в разделе 8.4.
Фраза “аналог v=v*(x)
” означает, что значение выражения v*=x
совпадает со значением выражения v=v*(x)
, за исключением того, что значение v вычисляется только один раз. Например, выражение v[++i]*=7+3
означает (++i, v[i]=v[i]*(7+3)
), а не (v[++i]=v[++i]*(7+3)
) (которое может быть неопределенным; см. раздел 8.6.1).
Результат выражения throw
имеет тип void
.
Каждая таблица содержит операторы, имеющие одинаковый приоритет. Операторы в более высоко расположенных таблицах имеют более высокий приоритет по сравнению с операторами, расположенными ниже. Например, выражение a+b*c
означает a+(b*c)
, а не (a+b)*c
, поскольку оператор *
имеет более высокий приоритет по сравнению с оператором +
. Аналогично, выражение *p++
означает *(p++)
, а не (*p)++
. Унарные операторы и операторы присваивания являются a=b=c
означает a=(b=c)
, а выражение a+b+c
означает (a+b)+c
. Lvalue
— это объект, допускающий модификацию. Очевидно, что объект lvalue
, имеющий спецификатор const
, защищен от модификации системой типов и имеет адрес. Противоположностью выражения lvalue
является выражение rvalue
, т.е. выражение, идентифицирующее нечто, что не может быть модифицировано или не имеет адреса, например, значение, возвращаемое функцией (&f(x)
— ошибка, поскольку значение, возвращаемое функцией f(x)
, является значением rvalue
).
A.5.1. Операторы, определенные пользователем
Правила, перечисленные выше, установлены для встроенных типов. Если же используется оператор, определенный пользователем, то выражение просто преобразовывается в вызов соответствующей операторной функции, определенной пользователем, и порядок действий определяется правилами, установленными для вызова функций. Рассмотрим пример.
class Mine { /* .. . */ };
bool operator==(Mine, Mine);
void f(Mine a, Mine b)
{
if (a==b) { // a==b означает operator==(a,b)
// ...
}
}
Тип, определенный пользователем, — это класс (см. главу 9, раздел A.12) или перечисление (см. разделы 9.5, A.11).
A.5.2. Неявное преобразование типа
Целочисленные типы или типы с плавающей точкой (раздел A.8) могут свободно смешиваться в операторах присваивания и в выражениях. При первой же возможности значения преобразовываются так, чтобы не потерять информацию. К сожалению, преобразования, уничтожающие значение, выполняются также неявно.
A.5.2.1. Продвижения
Неявные преобразования, сохраняющие значения, обычно называют float
в значение типа double
также считается продвижением.
Продвижения используются как часть обычных арифметических преобразований (раздел A.5.2.2).
A.5.2.2. Преобразования
Значения фундаментальных типов можно преобразовывать друг в друга самыми разными способами. При написании программы следует избегать неопределенного поведения и непредсказуемых преобразований, которые незаметно искажают информацию (см. разделы 3.9 и 25.5.3). Компиляторы обычно способны предупредить о многих сомнительных преобразованиях.