Топ питань
Часова шкала
Чат
Перспективи

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

З Вікіпедії, вільної енциклопедії

Remove ads

Тут наведено перелік операторів, що використовуються у мовах програмування C й C++. Усі наведені оператори присутні у C++. Якщо оператор також використовується у мові С, це буде відмічено у стовпчику "Присутній у С". Стовпчик "Можливість перевантаження" має сенс лише для мови C++, оскільки C не підтримує перевантаження операторів.

За відсутності перевантаження, для операторів &&, ||, та , (оператор кома), існує точка перебігу після обчислення першого операнду.

C++ також містить наступні оператори приведення типів const_cast, static_cast, dynamic_cast, та reinterpret_cast, які в таблиці не подані задля скорочення. Форматування цих операторів означає, що рівень їх пріоритету не є важливим.

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

Remove ads

Таблиця

Узагальнити
Перспектива

В даній таблиці символи a, b, та c - це будь-які значення (літерали, значення змінних, або повернені значення), імена об'єктів або інші значення, що мають адресу.

"Можливість перевантаження" означає, що даний оператор може бути перевантажений засобами C++, але не у мові С, оскільки вона не підтримує перевантаження операторів.
"Присутній у C" означає що даний оператор існує і має семантичний зміст у мові C.

Арифметичні оператори

Більше інформації Ім'я оператора, Синтаксис ...

Оператори порівняння/відношення

Більше інформації Оператор name, Синтаксис ...

Логічні оператори

Більше інформації Ім'я оператора, Синтаксис ...

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

Більше інформації Ім'я оператора, Синтаксис ...

Складені оператори присвоєння

Більше інформації Ім'я оператора, Синтаксис ...

Операції із вказівниками та членами

Більше інформації Ім'я оператора, Синтаксис ...

Інші оператори

Більше інформації Ім'я оператора, Синтаксис ...

Примітки:

  1. Оператор отримання остачі працює лише з цілочисельними операндами, для чисел з рухомою комою має бути застосована відповідна бібліотечна функція (наприклад fmod).
  2. В контексті потоків введення/виведення бібліотеки iostream, автори часто називають оператори << та >> як “вставити в” або "внесення в потік" та “взяти з” або "винесення з потоку", відповідно.
  3. Відповідно до стандарту C99, зсув вправо від'ємного числа залежить від його конкретної реалізації. У більшості реалізацій застосовується арифметичний зсув, але можливим є і логічний зсув.
  4. Приклад можна знайти у "Implementing operator->* for Smart Pointers" by Scott Meyers.
  5. У випадку, коли оператор ->* працює за замовчуванням, параметр R буде методом-покажчиком на метод класу Т і повернене значення нагадуватиме деякий функтор, що готовий до виклику з параметрами методу (і тільки ними).
  6. При визначенні розміру змінної, круглі дужки не обов'язкові, вони потрібні лише при визначенні розміру типу даних. Однак, зазвичай, вони все одно вживаються.
  7. У мові C++ визначено оператор alignof, тоді як у C _Alignof. Обидва оператори мають однакову семантику.
Remove ads

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

Узагальнити
Перспектива

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

Синтакс виразів у мовах C та C++ визначається контекстно-вільною граматикою. Наведена вище таблиця отримана на основі граматики.

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

Більше інформації Пріоритет, Оператор ...

Примітки

Таблиця пріоритету визначає порядок застосування (поєднання) операторів у складних виразах, коли цей порядок не заданий явно за допомогою круглих дужок.

  • Наприклад, вираз ++x*3 без застосування правил пріоритету має певну двозначність. Таблиця пріоритету каже нам, що: x тісніше 'пов'язаний' з ++, ніж з *, тому, щоб не робив оператор ++ (зараз чи пізніше), він робитиме це ТІЛЬКИ з x (а не з x*3); це еквівалентно виразу (++x, x*3).
  • Аналогічним чином, для виразу 3*x++, де постфіксний оператор інкременту ++ хоча і призначений діяти ПІСЛЯ обчислення усього виразу, але таблиця пріоритетів ясно вказує, що не зважаючи на це, інкрементується ТІЛЬКИ x (а не 3*x); це еквівалентно виразу подібному до (tmp=3*x, ++x, tmp), де tmp є тимчасовим значенням.
Thumb
Пріоритет та поєднання
  • Зобразимо проблему пріоритету операторів та їх поєднання у вигляді діаграми. Завданням компілятора є перетворення цієї діаграми у вираз, в якому декілька унарних операторів ( назвемо їх 3+( . ), 2*( . ), ( . )++ та ( . )[ i ] ) конфліктують за поєднання з y. Проблема вирішується за допомогою таблиці пріоритету, яка дозволяє сформувати остаточний набір виразів: ( . )[ i ] діє тільки на y, ( . )++ діє тільки на y[i], 2*( . ) діє тільки на y[i]++ та 3+( . ) діє 'тільки' на 2*((y[i])++). Важливо зазначити, що таблиця дозволяє визначити, який з виразів буде використаний кожним з операторів, але відповіді на питання "КОЛИ кожний оператор вступить в дію", таблиця не дає. В даному прикладі оператор ( . )++ діє тільки на y[i] за правилами таблиці, але самі по собі рівні поєднання не визначають час виконання суфікса ++ (оператор ( . )++ буде використаний лише після обчислення у виразі елементу y[i]).

Низка багатосимвольних операторів отримують власні "імена", побудовані з назв операторів для кожного свого символу. Наприклад, оператори += та -= часто називаються плюс дорівнює та мінус дорівнює, а не "присвоєння суми" та "присвоєння різниці", що було б громіздкіше.

Поєднання операторів у C та C++ визначається скоріше граматикою мови (викладеною у відповідних стандартах), а не таблицею пріоритету. Це створює деякі приховані конфлікти. Наприклад, у мові С, синтаксис для виразу з умовним переходом є таким:

logical-OR-expression ? expression : conditional-expression

в той час коли у C++ він такий:

logical-OR-expression ? expression : assignment-expression

Таким чином вираз:

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

у двох мовах граматично розбивається по різному. У мові C цей вираз є синтаксичною помилкою, але багато компіляторів розбивають вираз так:

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

що є семантичною помилкою, оскільки результат виразу з умовним переходом (яким може бути a++) не є адресованим значенням (lvalue). У C++ це розбивається як:

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

що є правильним виразом.

Пріоритет побітових операторів було розкритиковано . Концептуально, оператори & and | є арифметичними операторами, подібними до + and *.

Вираз a & b == 7 синтаксично розбивається як a & (b == 7), коли вираз a + b == 7 розбивається як (a + b) == 7. Це потребує частішого застосування круглих дужок.

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

C++ визначає[1] набір ключових слів, які можуть діяти як псевдоніми деяких операторів: and (&&), bitand (&), and_eq (&=), or (||), bitor (|), or_eq (|=), xor (^), xor_eq (^=), not (!), not_eq (!=), compl (~). Їх можна використовувати тим самим чином як і ті символи, які вони замінюють, оскільки псевдонім це не тільки той самий оператор, але під іншим ім'ям, але скоріше це є текстовий еквівалент імені відповідного оператора. Наприклад, bitand можна використати для заміни не тільки побітового оператора але і оператора отримання адреси і навіть використати для вказання типів посилань (наприклад: int bitand ref = n; замість int &ref = n; ).

Специфікація ANSI для мови C резервує ці ключові слова як макроси препроцесора у заголовному файлі iso646.h. З метою збереження сумісності із C, у мові C++ передбачено заголовний файл ciso646, додавання якого не дає жодного ефекту.

Remove ads

Посилання

Зовнішні посилання

Loading related searches...

Wikiwand - on

Seamless Wikipedia browsing. On steroids.

Remove ads