Лучшие вопросы
Таймлайн
Чат
Перспективы

Операторы в 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 ) { /* реализация */ }
  • «Н/Д»: недоступно.

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

Подробнее Операция (выражение), Оператор ...

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

Подробнее Операция (выражение), Оператор ...

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

Подробнее Операция (выражение), Оператор ...

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

Подробнее Операция (выражение), Оператор ...

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

Подробнее Операция (выражение), Оператор ...

Операторы работы с указателями и членами класса

Подробнее Оператор, Синтаксис ...

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

Подробнее Оператор, Синтаксис ...

Примечания:

  1. Оператор «%» работает только с целыми числами. Для чисел с плавающей точкой используйте функцию fmod() из файла «math.h».
  2. Чтобы отличить префиксный и суффиксный (постфиксный) операторы друг от друга, у постфиксных операторов добавлен неиспользуемый формальный параметр типа int. Часто этому параметру даже не дают имя.
  3. В библиотеке «iostream» операторы «<<» и «>>» используются для работы с потоковым выводом и вводом.
  4. По стандарту C99, сдвиг вправо отрицательного числа — implementation defined behavior (см. неуточняемое поведение). Многие компиляторы, в том числе gcc (см. документацию Архивная копия от 22 сентября 2019 на Wayback Machine (англ.)), реализуют арифметический сдвиг, но стандарт не запрещает реализовывать логический сдвиг.
  5. Тип возвращаемого значения оператора «operator->()» должен быть типом, к которому применим оператор «->», например, указателем. Если «x» имеет тип «C», и класс «C» перегружает оператор «operator->()», выражение «x->y» раскрывается как «x.operator->()->y».
  6. См. пример в статье Архивная копия от 17 мая 2013 на Wayback Machine (англ.) «Реализация оператора ->* для умных указателей» Скотта Майерса из журнала «Dr. Dobb’s journal», выпуск за октябрь 1999 года.
  7. Оператор sizeof, обычно, записывают со скобками. Если операнд — имя переменной, указание скобок необязательно. Если операнд — имя типа, скобки обязательны.
  8. Стандарт языка C++ определяет оператор alignof. Аналогичный оператор в стандарте языка Си называется _Alignof.
  9. Для оператора приведения типа тип возвращаемого значения явно не указывается, так как совпадает с именем оператора.
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.
Thumb
Приоритеты и связывание

Связывание операторов в стандартах Си и 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

Примечания

Ссылки

Loading related searches...

Wikiwand - on

Seamless Wikipedia browsing. On steroids.

Remove ads