Лучшие вопросы
Таймлайн
Чат
Перспективы
Операторы в C и C++
Из Википедии, свободной энциклопедии
Remove ads
Язык программирования C++ поддерживает все операторы своего прародителя Си и дополнен новыми операторами и возможностями.
- например, операторами приведения типа:
- возможность перегрузки операторов;
После вычисления первого операнда для неперегруженных операторов «&&», «||» и «,» (оператор «запятая», англ. comma) компилятор вставляет точку следования (англ. sequence point), гарантирующую, что все побочные эффекты (например, оператор «постфиксный ++») будут выполнены до начала вычисления второго операнда.
Языки с Си-подобным синтаксисом (например, Java, C#, PHP и другие) часто заимствуют операторы Cи/C++ с сохранением не только поведения, но также приоритета и ассоциативности.
Remove ads
Таблицы
Суммиров вкратце
Перспектива
В таблицах используются следующие обозначения:
- «a», «b» и «c»: имена объектов или значения (литералы, значения переменных, возвращаемые значения, lvalue);
- «Перегружаемый»: возможность перегрузки оператора в языке C++;
- «Реализован в Си»: существование оператора в языке Си;
- «R», «T», «S»: имена типов;
- «Пример»: пример объявления перегруженного оператора;
- «Член типа T»: определение оператора в виде метода структуры или класса (внутри структуры или класса); пример:
struct T { // или class
operator float () const;
};
T::operator float () const { /* реализация */ };
- «Определение вне класса»: определение оператора в виде функции; пример:
#include <iostream>
struct T { // или class
/* ... */
};
std::ostream & operator << ( std::ostream & a, T const & b ) { /* реализация */ }
- «Н/Д»: недоступно.
Арифметические операторы
Операторы сравнения
Логические операторы
Побитовые операторы
Составное присваивание
Операторы работы с указателями и членами класса
Другие операторы
Примечания:
- Чтобы отличить префиксный и суффиксный (постфиксный) операторы друг от друга, у постфиксных операторов добавлен неиспользуемый формальный параметр типа
int
. Часто этому параметру даже не дают имя. - По стандарту C99, сдвиг вправо отрицательного числа — implementation defined behavior (см. неуточняемое поведение). Многие компиляторы, в том числе gcc (см. документацию Архивная копия от 22 сентября 2019 на Wayback Machine (англ.)), реализуют арифметический сдвиг, но стандарт не запрещает реализовывать логический сдвиг.
- Тип возвращаемого значения оператора «
operator->()
» должен быть типом, к которому применим оператор «->
», например, указателем. Если «x
» имеет тип «C
», и класс «C
» перегружает оператор «operator->()
», выражение «x->y
» раскрывается как «x.operator->()->y
». - См. пример в статье Архивная копия от 17 мая 2013 на Wayback Machine (англ.) «Реализация оператора
->*
для умных указателей» Скотта Майерса из журнала «Dr. Dobb’s journal», выпуск за октябрь 1999 года. - Оператор
sizeof
, обычно, записывают со скобками. Если операнд — имя переменной, указание скобок необязательно. Если операнд — имя типа, скобки обязательны. - Стандарт языка C++ определяет оператор
alignof
. Аналогичный оператор в стандарте языка Си называется_Alignof
. - Для оператора приведения типа тип возвращаемого значения явно не указывается, так как совпадает с именем оператора.
Remove ads
Приоритеты операторов
Суммиров вкратце
Перспектива
В данной таблице указаны приоритеты операторов и их ассоциативность. Операторы, указанные в таблице выше (раньше), имеют более высокий приоритет (приоритет вычисления). При рассмотрении выражения, операторы, имеющие более высокий приоритет, будут вычислены раньше операторов с низким приоритетом. Если несколько операторов указаны в одной ячейке, то они имеют одинаковый приоритет и вычисляются в последовательности, задаваемой ассоциативностью. Приоритеты операторов не изменяются при их перегрузке.
Этой таблицы приоритетов в большинстве случаев бывает достаточно, за исключением следующих случаев. Тернарный оператор «?:» может содержать в среднем выражении оператор «запятая» или присваивание, но код «a ? b, c : d
» компилятор воспринимает как «a ? (b, c) : d
», а не как бессмысленное выражение «(a ? b), (c : d)
». Таким образом выражение между ?
и :
воспринимается, как если бы оно было в скобках.
Описание
Компилятор использует таблицу приоритетов для определения порядка вычисления операторов.
- Например,
++x*3
был бы двусмысленным без каких-либо правил приоритетов. По таблице можно сказать, что x сначала связывается с оператором ++, и только затем с оператором *, поэтому независимо от действия оператора ++, это действие только над x (а не надx*3
). Таким образом, выражение эквивалентно (++x
,x*3
). - Аналогично с кодом
3*x++
, где таблица утверждает, что инкремент применяется только к x а не к3*x
. Функционально это выражение эквивалентно (tmp=x,
x++, tmp=
3*tmp,tmp
), если выразить временную переменную как tmp.

Связывание операторов в стандартах Си и C++ определено через грамматику языка, а не через таблицу. Это может создать конфликт. Например, в языке Си синтаксис условного оператора таков:
logical-OR-expression ? expression : conditional-expression
А в языке C++:
logical-OR-expression ? expression : assignment-expression
Из-за этого выражение:
e = a < d ? a++ : a = d
будет воспринято по-разному в этих двух языках. В Си выражение синтаксически некорректно, так как результат условного оператора не может служить lvalue (то есть, левой частью оператора присваивания).
В C++, выражение будет разобрано как корректное:[1]
e = (a < d ? a++ : (a = d))
Приоритеты побитовых логических операторов несколько неинтуитивны[2]. Концептуально &
и |
являются такими же арифметическими операторами как *
и +
соответственно.
Выражение a & b == 7
синтаксически воспринимается как a & (b == 7)
, но выражение a + b == 7
эквивалентно (a + b) == 7
. Из-за этого часто требуется пользоваться скобками для явного задания порядка вычислений.
Синонимы операторов в C++
В стандарте C++ определены[3] диграфы для некоторых операторов:
Диграфы могут использоваться точно так же как и операторы, являются синонимами операторов. Например, диграф «bitand
» может использоваться для замены операторов «побитовое И» и «получение адреса» или в определении ссылочных типов. Так, код «int bitand ref = n;
» эквивалентен коду «int & ref = n;
».
Стандарт ANSI/ISO C определяет перечисленные диграфы в виде констант #define
(см. препроцессор). Константы определены в заголовочном файле «iso646.h
». Для совместимости с Си стандарт C++ определяет фиктивный заголовочный файл «ciso646
».
Remove ads
Примечания
Ссылки
Wikiwand - on
Seamless Wikipedia browsing. On steroids.
Remove ads