Тип умовного вираження
Вирази
У файлі enum_tst.cpp
enum signal { off, on } a = on; //а присвоєно значення on
enum answer { no, yes, maybe = - 1 } b;
enum negative { no, false } с; //неприпустимо, no та
//false переоголошені
int i, j = on; //допустимо, on
//перетворена в 1
а = off; / /допустимо
i = а ; //допустимо, i стає 0
b = а; //неприпустимо
//два різні типи
b = static_cast<answer>(а); //допустимі, явне приведення
b = (а ? no: yes); //допустиме, перераховане
//константи типу answer
Константи, що перераховують, можуть оголошуватися анонімно, без тегового імені. Наприклад:
enum { LB = 0, UB = 99 };
enum { lazy, hazy, crazy } why;
Перше оголошення ілюструє звичайний спосіб завдання мнемонічних цілих констант. У другому рядку оголошується змінна why (причина) типу, що перераховує, з допустимими значеннями lazy (ледачий), hazy (піддатливий) і crazy (божевільний).
У C++ є безліч форм операторів і виразів. Наприклад, привласнення є вираженням. Наступне допустимо в C++:
а = b+ (c = d + 3 );
Використання арифметичних виразів в C++ узгоджується із звичайною практикою. Одно важлива відмінність полягає в тому, що результат оператора ділення ( / ) залежить від типу аргументів.
а = 3 / 2;
а = 3 / 2.0;
Друга важлива відмінність полягає в тому, що в C++ прийнята терпима позиція по відношенню до зменшення типів і автоматичного перетворення. C++ допускає розширяльні перетворення типів, так що int може бути розширений до double при привласненні. З іншого боку, в C++ дозволяються привласнення з перетворенням до вужчого типу; так, double може бути присвоєний типу int і навіть char.
int i ;
char ch;
double b = 1.9;
i = b / 2.0; //i присвоено значение 0
ch = 'А' + 1.0; //ch равно 'В'
Таке ліберальне відношення C++ до перетворень сприяє поганому стилю програмування і не повинно заохочуватися. Перетворення, що звужують типи, і змішані типи можуть впливати на правильність програми і повинні застосовуватися з обережністю.
У сучасних системах C++ для контролю за потоком управління в інструкціях різних типів використовуються булеві значення true і false. У наступній таблиці представлені інструкції C++, найчастіше використовувані для управління логікою виконання.
Оператори порівняння, рівність і логічні | ||
Оператори порівняння | менше | < |
більше | > | |
менше або рівно | < = | |
більше або рівно | >= | |
Оператори рівності | рівно | == |
не рівно | 1 = | |
Логічні оператори | (унарне) заперечення | |
логічне і | && | |
логічне або | | | |
Для операторів порівняння, рівності і логічних, також як і для усіх інших, існують правила пріоритету і порядку виконання, точно визначальні, як повинні обчислюватися у вирази, ці оператори, що містять. Оператор заперечення ! є унарним. Усі інші оператори порівняння, рівність і логічні оператори — бінарні. Вони діють на вирази і виробляють булеві значення false або true. Це замінює більше ранню угоду C++, коли типу bооl в мові не існувало, і за fаlsе приймався нуль, а за true — не нуль. Проте там, де очікується логічне значення, арифметичне вираження автоматично перетвориться відповідно до цієї угоди, так що нуль розуміється як false, а не нуль — як true. Тобто старий стиль програмування як і раніше працює коректно.
Одна з пасток C++ полягає в тому, що оператори рівності і привласнення візуально схожі. Вираження а = = b є перевіркою на рівність, тоді як а = b — цей вираз привласнення. Одна з найбільш поширених помилок програмування на C++ може виглядати як-небудь так:
if (i = 1)
//робити що-небудь
Звичайно, малося на увазі
if (i = =1)
//робити що-небудь
У першій інструкції if змінної i привласнюється значення 1, і результат вираження привласнення також дорівнює 1, тому умова в дужках буде завжди виконана (не нуль, тобто true). Подібну помилку буває дуже важко знайти.
Логічні оператори !, && і | | виробляють булеве значення true або false. Логічне заперечення може бути застосоване до будь-якого вираження. Якщо вираження мало значення false, то його заперечення виробить true.
Пріоритет && вищий, ніж | |, але обидва оператори мають нижчий пріоритет, ніж усі унарні, арифметичні оператори і оператори порівняння. Порядок їх виконання — зліва направо.
При обчисленні виразів, що є операндами && і | |, процес обчислення припиняється, як тільки відомий результат, true або false. Це називається обчисленням за короткою схемою (short — circuit evaluation). Нехай expr1 і ехрг2 — вирази. Якщо expr1 має значення false, то в
expr1 && expг2
ехрr2 не обчислюватиметься, оскільки значення логічного виразу вже визначене як false. Аналогічно, якщо expr1 є true, то в
expr1 || ехрr2
ехрr2 не обчислюватиметься, оскільки значення логічного виразу вже визначене як true.
З усіх операторів C++ у оператора кома найнижчий пріоритет. Це бінарний оператор з виразами в якості операндів. У вираженні з комою виду
expr1, ехрr2
першим обчислюється expr1, потім ехрr2. Усs вираження з комою в цілому мають значення і тип свого правого операнда. Наприклад
sum = 0, i = 1
Якщо i була оголошена як ціле, то це вираження з комою має значення 1 і тип int. Оператор кома зазвичай застосовується в контрольному вираженні ітераційного процесу, коли однієї дії недостатньо. Порядок виконання операторів кома — зліва направо.
Умовний оператор ? : незвичайний тим, що це потрійний оператор. Він приймає як операнди три вираження. У конструкції
expr1 ? ехрr2: ехрrЗ
першим обчислюється вираження expr1. Якщо воно істинне, то обчислюється ехрr2, і воно стає значенням умовного вираження в цілому. Якщо expr1 помилково, то обчислюється ехрrЗ, і вже воно стає значенням умовного вираження в цілому. У наступному прикладі умовний оператор використовується для привласнення змінної х найменшого з двох значень:
х = (у < z)? у: z;
Дужки тут не обов'язкові, оскільки оператор порівняння має вищий пріоритет, ніж оператор привласнення. Проте, використання дужок — це хороший стиль, оскільки з ними ясно, що з чим порівнюється.
ехрr1 ? ехрr2: ехрrЗ
визначається операндами ехрr2 і ехрrЗ. Якщо вони різних типів, то застосовуються звичайні правила перетворення. Тип умовного вираження не може залежати від того, який з двох виразів ехрr2 або ехрrЗ буде вичислено. Порядок виконання умовних операторів ? : — справа наліво.
С++ надає бітові оператори. Вони діють на машинно-залежне бітове представлення цілих операндів.
Бітовий оператор | Значення |
~ | побітове заперечення |
<< | побітове зрушення вліво |
>> | побітове зрушення управо |
& | побітове І |
^ | що побітове виключає АБО |
| | побітове АБО |
Зазвичай оператори зрушення перевантажуються для здійснення введення-виводу.
У C++ виклик функції () і індексація масиву [] розглядаються як оператори. Існують також оператор визначення адреси & і оператор звернення за адресою або переіменування *. Оператор визначення адреси є унарним; він повертає адресі пам' яті, по якій зберігається об' єкт. Оператор звернення за адресою також є унарним і застосовується до покажчиків. З його допомогою можна отримати значення за адресою, на які посилається покажчик. Це називається переіменуванням покажчика.
У C++ також є оператор sizeof, який використовується для визначення того, скільки байт знадобиться для зберігання конкретного об'єкту. Для динамічно розподілюваних об'єктів дуже важливо виділяти достатній об'єм пам'яті.