Операторы в C и C ++

редактировать
Схожий синтаксис на обоих компьютерных языках

Это список операторы в языках программирования C и C++ . Все перечисленные операторы существуют в C ++; четвертый столбец «Включено в C» указывает, присутствует ли оператор также в C. Обратите внимание, что C не поддерживает перегрузку операторов .

Если не перегружен, для операторов , ||и ,(оператор запятая ), после вычисления первого операнда находится точка последовательности.

C ++ также содержит операторы преобразования типов const_cast, static_cast, dynamic_castи reinterpret_cast <146.>. Форматирование этих операторов означает, что их уровень приоритета не важен.

Большинство операторов, доступных в C и C ++, также доступны в других языках семейства C, таких как C#, D, Java, Perl и PHP с тем же приоритетом, ассоциативностью и семантикой.

Содержание
  • 1 Таблица
    • 1.1 Арифметические операторы
    • 1.2 Операторы сравнения / операторы отношения
    • 1.3 Логические операторы
    • 1.4 Побитовые операторы
    • 1.5 Операторы составного присваивания
    • 1.6 Член и указатель операторы
    • 1.7 Другие операторы
  • 2 Приоритет операторов
    • 2.1 Примечания
    • 2.2 Критика приоритета побитовых операторов и операторов равенства
    • 2.3 Синонимы операторов C ++
  • 3 См. также
  • 4 Ссылки
  • 5 Внешние ссылки
Таблица

Для целей этих таблиц a, bи cпредставляют допустимые значения (литералы, значения из переменных или возвращаемое значение), имена объектов, или lvalues, в зависимости от ситуации. R, Sи Tобозначают любой тип (типы), а K- тип класса или перечислимый тип.

Арифметические операторы

Имя оператораСинтаксисВозможна перегрузка в C ++Включено. в C примеры прототипов C ++
Как член KОпределения внешнего класса
Базовое присвоение a =bДаДаR K :: operator = (S b);Н / Д
Сложение a +bДаДаRK :: оператор + (S b);R оператор + (K a, S b);
Вычитание a -bДаДаRK :: operator - (S b);R operator - (K a, S b);
Унарный плюс (целочисленное продвижение )+aДаДаRK :: operator + ();R operator + (K a);
Унарный минус (аддитивный обратный )-aДаДаRK :: operator - ();R operator - (K a);
Умножение a *bДаДаRK :: operator * (S b);R оператор * (K a, S b);
Разделение a /bДаДаRK :: operator / (S b);Оператор R / (K a, S b);
по модулю (целочисленный остаток)a %bДаДаRK :: operator% (S b);R оператор% (K a, S b);
Приращение Префикс++aДаДаR K :: operator ++ ();R operator ++ (Ka);
Postfixa++ДаДаRK: : operator ++ (int);R operator ++ (K a, int);
Примечание: C ++ использует безымянный фиктивный параметр int, чтобы различать операторы префиксного и постфиксного приращения.
Уменьшение Префикс--aДаДаОператор R K :: - ();Оператор R - (K a);
Постфиксa--ДаДаRK :: operator - (int);R operator - (K a, int);
Примечание: C ++ использует безымянный фиктивный параметр int, чтобы различать префиксные и постфиксные операторы декремента.

Операторы сравнения / операторы отношения

Имя оператораСинтаксисВозможна перегрузка в C ++Включено. в C Примеры прототипов
Как член KОпределения внешнего класса
Равноa ==bДаДаbool K :: operator == (S const b) const;оператор bool == (K const a, S const b);
Не равноa !=b. a not_eqbДаДаbool K :: operator! = (S const b);bool K :: operator! = (S const b) const;bool operator! = (K const a, S const b);
Больше, чемa>bДаДаbool K :: operator>(S const b) const;bool operator>(K const a, S const b);
Меньшеa ДаДаbool K :: operator <(S constb) const;bool operator <(K consta, S constb);
Больше или равноa>=bДаДаbool K :: operator>= (S const b) const;bool operator>= (K const a, S const b);
Меньше или равноa <=bДаДаbool K :: operator <=(S constb) const;bool operator <=(K consta, S constb);
Трехстороннее сравнение a <=>bДаНетул. d :: weak_equality K :: operator <=>(const S b);std :: weak_equality operator <=>(const K a, const S b);
Примечание: у оператора всего 6 возвращаемые типы: std :: weak_equality, std :: strong_equality, std :: partial_ordering, std :: weak_ordering, std :: strong_orderingи std :: common_comparison_category

Логические операторы

Имя оператораСинтаксисВозможна перегрузка в C ++Включено. в C примерах прототипов C ++
Как член KОпределения внешних классов
Логическое отрицание (НЕ) !a. не aДаДаbool K :: operator! ();bool operator! (K a);
Логическое И a b. a и bДаДаbool K :: operator (S b);логический оператор (K a, S b);
Логическое ИЛИ a ||b. a orbДаДалогический оператор K :: || (S b) ;логический оператор || (K a, S b);

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

Имя оператораСинтаксисВозможна перегрузка в C ++Включено. в C Экзамен прототипа ples
Как член KОпределения внешних классов
Побитовое НЕ ~a. Compl aДаДаRK :: operator ~ ();R оператор ~ (K a);
Побитовое И a b. a бит и bДаДаRK :: operator (S b);R оператор (K a, S b);
Поразрядное ИЛИ a |b. a битор bДаДаRK :: operator | (S b);R operator | (K a, S b);
Побитовое исключающее ИЛИ a ^b. a xor bДаДаRK :: operator ^ (S b);R operator ^ (K a, S b);
Побитовый сдвиг влево a <ДаДаRK :: operator <<(S b);R operator <<(K a, S b);
Побитовый сдвиг вправо a>>bДаДаRK :: operator>>(S b);R operator>>(K a, S b);

Составные операторы присваивания

Имя оператораСинтаксисЗначениеВозможна перегрузка в C ++Включено. в C примеры прототипов C ++
Как член KОпределения внешних классов
Добавление присваиванияa +=ba =a +bДаДаR K :: operator + = (S b);R operator + = (K a, S b);
Присваивание вычитанияa -=ba =a -bДаДаR K :: operator - = (S b);R operator - = (K a, S b);
Присвоение умноженияa *=ba =a *bДаДаR K :: operator * = (S b);R operator * = (K a, S b);
Назначение деленияa /=ba =a /bДаДаR K :: operator / = (S b);R operator / = (K a, S b);
Присвоение по модулюa %=ba =a %bДаДаRK :: operator% = (S b);R operator% = (K a, S b);
Побитовое И присваиваниеa =b. a and_eq ba =a bДаДаRK: : operator = (S b);R operator = (K a, S b);
Назначение побитового ИЛИa |=b. a or_eq ba =a |bДаДаRK :: operator | = (S b);R operator | = (K a, S b);
Побитовое присвоение XORa ^=b. a xor_eq ba =a ^bДаДаR K :: operator ^ = (S b);R operator ^ = (K a, S b);
Назначение побитового сдвига влевоa <<=ba =a <ДаДаRK: : operator <<=(S b);R operator <<=(Ka, S b);
Назначение побитового сдвига вправоa>>= ba =a>>bДаДаRK :: operator>>= (S b);R operator>>= (K a, S b);

Операторы-члены и указатели

O имя оператораСинтаксисВозможна перегрузка в C ++Включено. в C Примеры прототипов C ++
Как член KСнаружи определения классов
Нижний индекс a[b]ДаДаR K :: operator (S b);.Н / Д
Косвенное обращение ("объект, на который указывает символ")*aДаДаR K :: operator * ();R operator * (K a);
Address-of ("адрес a")aДаДаR * K :: operator ();R * operator (K a);
Разыменование структуры ("элемент b объекта, на который указывает a")a->bДаДаR * K :: operator ->();.Н / Д
Ссылка на структуру («элемент b объекта a»)a.bNoДаН / Д
Элемент, выбранный параметром b объекта, на который указываетa->* bДаНетОператор R K :: ->* (S b);R operator ->* (K a, S b);
Элемент объекта a, выбранный ba.*bNoНетN / A

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

Имя оператораСинтаксисВозможна перегрузка в C ++Включено. в C Примеры прототипов
Как член KОпределения внешних классов
Функция вызов. См. Функциональный объект.a(a1, a2 )ДаДаRK :: operator () (S a, T b,...);Н / Д
Запятая a,bДаДаRK :: operator, (S b);R operator, (K a, S b);
Тернарная условная a ?b :cNoДаН / Д
Разрешение области a::bNoНетН / Д
Определяется пользователем литералы. начиная с C ++ 11"a"_bДаНетН / ДОператор R "" _b (T a)
Sizeof sizeof (a). sizeof (type)NoДаН / Д
Размер пакета параметров. с C ++ 11sizeof... (Args)NoНетN / A
. с C ++ 11alignof (type). или _Alignof (тип)NoДаН / Д
Идентификация типаtypeid (a). typeid (тип)NoНетН / Д
Преобразование (приведение в стиле C)(тип) aДаДаK :: operator R ();Н / Д
Преобразование тип (a)NoНетПримечание: ведет себя как const_cast / static_cast / reinterpret_cast
static_cast преобразованиеstatic_cast(a)ДаНетK :: operator R ();. явный K :: оператор R ();начиная с C ++ 11Н / Д
Примечание: для пользовательских преобразований тип возвращаемого значения неявно и обязательно соответствует имени оператора.
динамическое приведение преобразованиединамическое_кастирование(a)NoНетН / Д
const_cast преобразованиеconst_cast (a)NoНетН / Д
reinterpret_cast преобразованиеreinterpret_cast(a)NoНетН / Д
Выделить хранилище новый типДаНетvoid * K :: operator new (size_t x);void * operator new ( size_t x);
Выделить хранилище (массив)newtype[n]ДаНетvoid * K :: operator new (size_t a);void * operator new (size_t a);
Освободить память delete aДаНетvoid K :: operator delete (void * a);void operator delete ( void * a);
Освободить память (массив)удалить aДаНетvoid K :: operator delete (void * a);void operator delete ( void * a);
Проверка исключений. начиная с C ++ 11noexcept (a)NoНетН / Д

Примечания:

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

В следующей таблице перечислены приоритет и ассоциативность Все операторы на языках C и C ++ (когда операторы также существуют в Java, Perl, PHP и для многих других недавних языков приоритет такой же, как и данный). Операторы перечислены сверху вниз в порядке убывания приоритета. Нисходящий приоритет относится к приоритету группировки операторов и операндов. Учитывая выражение, оператор, который указан в некоторой строке, будет сгруппирован перед любым оператором, который указан в строке ниже. Операторы, находящиеся в одной ячейке (в ячейке может быть несколько строк операторов), группируются с одинаковым приоритетом в заданном направлении. Приоритет оператора не зависит от перегрузки.

Синтаксис выражений в C и C ++ определяется грамматикой структуры фраз . Приведенная здесь таблица была выведена из грамматики. Для стандарта ISO C 1999 в примечании 71 раздела 6.5.6 указано, что грамматика C, предусмотренная спецификацией, определяет приоритет операторов C, а также говорится, что приоритет операторов, вытекающий из грамматики, точно соответствует порядку разделов в спецификации:

"Синтаксис [C] [т. Е. Грамматика] определяет приоритет операторов при оценке выражения, который совпадает с порядком основных подпунктов этого подпункта, высший приоритет сначала. "

Таблица приоритетов, хотя в основном адекватная, не может разрешить некоторые детали. В частности, обратите внимание, что тернарный оператор допускает любое произвольное выражение в качестве своего среднего операнда, несмотря на то, что он указан как имеющий более высокий приоритет, чем присвоение и операторы запятой. Таким образом, a? b, c: dинтерпретируется как a? (b, c): d, а не как бессмысленное (a? b), (c: d). Таким образом, выражение в середине условного оператора (между ?и :) анализируется, как если бы p озвучены. Также обратите внимание, что непосредственный, без скобок результат выражения приведения C не может быть операндом sizeof. Следовательно, sizeof (int) * xинтерпретируется как (sizeof (int)) * x, а не sizeof ((int) * x).

ПриоритетОператорОписаниеАссоциативность
1

наивысшее

::Разрешение области (только C ++)Нет
2++Постфиксное приращениеСлева направо
--Постфиксный декремент
()Вызов функции
Индексирование массива
.Выбор элемента по ссылке
->Выбор элемента с помощью указателя
typeid ()Тип времени выполнения информация (только C ++) (см. typeid )
const_castПриведение типа (только C ++) (см. const_cast )
dynamic_castПриведение типа (только C ++) (см. динамическое приведение )
reinterpret_castприведение типа (только C ++) (см. reinterpret_cast )
static_castприведение типа (только C ++) (см. static_cast )
3++приращение префиксаСправа налево
--Префиксный декремент
+Унарный плюс
-Унарный минус
!Логическое НЕ
~Побитовое НЕ (дополнение до единицы)
(тип)Приведение типа
*Косвенное обращение (разыменование)
Address-o f
sizeofSizeof
_AlignofТребование выравнивания (начиная с C11)
new, newДинамическое распределение памяти (только C ++)
delete, deleteДинамическое освобождение памяти (только C ++)
4.*Указатель на член (только C ++)Слева направо
->*Указатель на член ( Только C ++)
5*УмножениеСлева направо
/Деление
%По модулю (остаток)
6+СложениеСлева направо
-Вычитание
7<<Побитовое сдвиг влевоСлева направо
>>Побитовое сдвиг вправо
8<=>Трехстороннее сравнение (введено в C ++ 20 - только C ++)Слева направо
9<МеньшеСлева направо
<=Меньше или равно
>Больше
>=Больше или равно
10==РавноСлева направо
!=Не равно
11Побитовое ИСлева направо справа
12^Поразрядное ИЛИ (исключающее ИЛИ)Слева направо
13|Поразрядное ИЛИ (включительно ИЛИ)Слева направо
14Логическое ИL eft-to-right
15||Логическое ИЛИСлева направо
16?:Тройное условное (см. ?: )Справа налево
=Прямое присвоение
+=Присвоение по сумме
-=Присвоение по разнице
*=Присвоение по продукту
/=Присвоение по частному
%=Присвоение по остатку
<<=Присвоение с помощью побитового сдвига влево
>>=Назначение с помощью побитового сдвига вправо
=Назначение с помощью побитового И
^=Назначение с помощью побитового ИЛИ
|=Назначение с помощью побитового ИЛИ
throwОператор выброса (генерирование исключений, только C ++)
17

самый низкий

,Запятая Слева направо

Примечания

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

  • Например, ++ x * 3является неоднозначным без какого-либо правила (правил) приоритета. Таблица приоритетов сообщает нам, что: xболее жестко «привязан» к ++, чем к *, так что все, что ++делает (сейчас или позже - см. ниже), он делает это ТОЛЬКО с x(а не с x * 3); он эквивалентен (++ x, x * 3).
  • Аналогично, с 3 * x ++, где хотя пост-исправление ++разработан, чтобы действовать ПОСЛЕ оценки всего выражения, таблица приоритетов дает понять, что ТОЛЬКО xувеличивается (а НЕ 3 * x). Фактически, выражение (tmp = x ++, 3 * tmp) оценивается с tmp, являющимся временным значением. Функционально это эквивалентно чему-то вроде (tmp = 3 * x, ++ x, tmp).
Приоритет и привязки
  • Если абстрагироваться от вопроса приоритета или привязки, рассмотрим приведенную выше диаграмму для выражения 3 + 2 * y [i] ++. Задача компилятора - преобразовать диаграмму в выражение, в котором используются несколько унарных операторов (назовем их 3+ (.), 2 * (.), (.) ++ и (.) [I]) конкурируют за связывание с y. Таблица приоритета определяет последнее подвыражение, над которым они действуют: (.) ​​[i] действует только на y, (.) ++ действует только на y [i], 2 * (.) действует только на y [i] ++, а 3+ (.) действует только на 2 * ((y [i]) ++). Важно отметить, что подвыражение ЧТО выполняется каждым оператором, ясно из таблицы приоритета, но КОГДА каждый оператор действует, таблица приоритета не разрешает; в этом примере оператор (.) ++ действует только на y [i] в ​​соответствии с правилами приоритета, но только уровни привязки не указывают время постфикса ++ (оператор (.) ++ действует только после y [i ] оценивается в выражении).

Многим операторам, содержащим многосимвольные последовательности, присваиваются «имена», составленные из имени оператора каждого символа. Например, + =и - =часто называют плюс равным (я) и минус равным (я), вместо более подробных "присвоение путем сложения" и "присвоение путем вычитания". ". Связывание операторов в C и C ++ определяется (в соответствующих Стандартах) грамматикой факторизованного языка, а не таблицей приоритетов. Это создает некоторые тонкие конфликты. Например, в C синтаксис условного выражения:

выражение-логическое ИЛИ? выражение: условное-выражение

, а в C ++ это:

логическое-ИЛИ-выражение? выражение: выражение-присваивания

Следовательно, выражение:

e = a < d ? a++ : a = d

анализируется по-разному на двух языках. В C это выражение является синтаксической ошибкой, потому что синтаксис выражения присваивания в C следующий:

unary-expression '=' assignment-expression

В C ++ он анализируется как:

e = ( a < d ? a++ : (a = d))

, которое является допустимым выражением.

Если вы хотите использовать оператор-запятую в одном аргументе функции, назначении переменных или другом списке, разделенном запятыми, вам необходимо использовать круглые скобки, например:

int a = 1, b = 2, weirdVariable = (++ a, b), d = 4;

Критика приоритета побитовых операторов и операторов равенства

Приоритет побитовых логических операторов имеет подверглись критике. Концептуально и | являются арифметическими операторами, такими как * и +.

Выражение a b == 7синтаксически разбирается как a (b == 7), тогда как выражение a + b == 7разбирается как (a + b) == 7. Это требует, чтобы скобки использовались чаще, чем в противном случае.

Исторически не существовало синтаксического различия между побитовыми и логическими операторами. BCPL, B и ранняя версия C, операторы ||не существовали. Вместо этого |имеет разное значение в зависимости от того, используются ли они в «контексте истинного значения» (т.е. когда ожидалось логическое значение, например в if (a == b c) {...}он вёл себя как логический оператор, но в c = a bон вёл себя как побитовый). Он был сохранен для сохранения обратной совместимости с существующими установками.

Более того, в C ++ (и более поздних версиях C) операции равенства, за исключением оператора трехстороннего сравнения, yield bool значения типа, которые концептуально представляют собой один бит (1 или 0) и, как таковые, не принадлежат должным образом к «побитовым» операциям.

Синонимы операторов C ++

C ++ определяет определенные ключевые слова, которые действуют как псевдонимы для ряда операторов:

KeywordOperator
и
and_eq=
bitand
bitor|
comp~
not!
not_eq!=
or||
or_eq|=
xor^
xor_eq^=

Их можно использовать точно так же, как символы пунктуации, которые они заменяют, поскольку они - это не один и тот же оператор под другим именем, а скорее простая замена токена для имени (символьной строки) соответствующего оператора. Это означает, что выражения (a>0, а не flag)и (a>0 ! Flag)имеют одинаковые значения. Это также означает, что, например, ключевое слово bitandможно использовать для замены не только побитового оператора И, но также оператора адресации, и оно может даже использоваться для указания ссылочных типов (например, int бит и ref = n). Спецификация ISO C допускает использование этих ключевых слов в качестве макросов препроцессора в файле заголовка iso646.h. Для совместимости с C C ++ предоставляет заголовок ciso646, включение которого не имеет никакого эффекта.

См. Также
Ссылки
Внешние ссылки
Последняя правка сделана 2021-06-01 13:13:38
Содержание доступно по лицензии CC BY-SA 3.0 (если не указано иное).
Обратная связь: support@alphapedia.ru
Соглашение
О проекте