Главная
Новости
Строительство
Ремонт
Дизайн и интерьер




18.04.2021


18.04.2021


18.04.2021


18.04.2021


18.04.2021





Яндекс.Метрика

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

04.07.2021

Язык программирования C++ поддерживает все операторы своего прародителя Си и дополнен новыми операторами и возможностями.

  • например, операторами приведения типа:
    • const_cast
    • static_cast
    • dynamic_cast
    • reinterpret_cast
  • возможность перегрузки операторов;

После вычисления первого операнда для неперегруженных операторов «&&», «||» и «,» (оператор «запятая», англ. comma) компилятор вставляет точку следования (англ. sequence point), гарантирующую, что все побочные эффекты (например, оператор «постфиксный ++») будут выполнены до начала вычисления второго операнда.

Языки с Си-подобным синтаксисом (например, Java, C#, PHP и другие) часто заимствуют операторы Cи/C++ с сохранением не только поведения, но также приоритета и ассоциативности.

Таблицы

В таблицах используются следующие обозначения:

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

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


    Этой таблицы приоритетов в большинстве случаев бывает достаточно, за исключением следующих случаев. Тернарный оператор «?:» может содержать в среднем выражении оператор «запятая» или присваивание, но код «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++, выражение будет разобрано как корректное:

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

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

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

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

    В стандарте C++ определены диграфы для некоторых операторов:

    Диграфы могут использоваться точно так же как и операторы, являются синонимами операторов. Например, диграф «bitand» может использоваться для замены операторов «побитовое И» и «получение адреса» или в определении ссылочных типов. Так, код «int bitand ref = n;» эквивалентен коду «int & ref = n;».

    Стандарт ANSI/ISO C определяет перечисленные диграфы в виде констант #define (см. препроцессор). Константы определены в заголовочном файле «iso646.h». Для совместимости с Си стандарт C++ определяет фиктивный заголовочный файл «ciso646».