Пріоритет та порядок виконання операцій сі. Пріоритет та порядок виконання. Елементарне введення-виведення в мові Сі

Пріоритет та порядок виконання

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

У таблиці 4.1 наведено операції у порядку зменшення пріоритету. Операції, розташовані в одному рядку таблиці або об'єднані в одну групу, мають однаковий пріоритет і однакову асоціативність.

Таблиця 4.1.

Пріоритет та асоціативність операцій у мові Сі

Знак операції Найменування Асоціативність
() . -> Первинні Зліва направо
+ - ~! * & ++ - sizeof приведення типу Унарні Справа наліво
* / % Мультиплікативні Зліва направо
+ - Адитивні Зліва направо
>> << Зрушення Зліва направо
< > <= >= Ставлення Зліва направо
== != Ставлення Зліва направо
& Порозрядне І Зліва направо
^ Порозрядне виключне АБО Зліва направо
| Порозрядне, що включає АБО Зліва направо
&& Логічне І Зліва направо
|| Логічне АБО Зліва направо
?: Умовна Справа наліво
= *= /= %= += -= <<= >>= &= |= ^= Просте та складове привласнення Справа наліво
, Послідовне обчислення Зліва направо

З таблиці 4.1. слід, що операнди, що представляють виклик функції, індексний вираз, вираз вибору елемента і вираз у дужках мають найбільший пріоритет і асоціативність зліва направо. Приведення типу має той самий пріоритет і порядок виконання, як і унарні операції.

Вираз може містити кілька операцій одного пріоритету. Коли кілька операцій однієї й тієї ж рівня пріоритету виявляються у виразі, всі вони застосовуються відповідно до їх асоціативністю - або праворуч наліво, або зліва направо.

Слід зазначити, що у мові Сі прийнято невдалий порядок пріоритету деяких операцій, зокрема операції зсуву і порозрядних операцій. Вони мають нижчий пріоритет, ніж арифметичні операції(Додаток та ін). Тому вираз

а = b & 0xFF + 5

обчислюється як

а = b & (0xFF + 5),

а вираз

а+с >> 1

обчислюється як

(а+с) >> 1

Мультиплікативні, адитивні та порозрядні операції мають властивість комутативності. Це означає, що результат обчислення виразу, що включає кілька комутативних операцій однієї й тієї ж пріоритету, залежить від порядку виконання цих операцій. Тому компілятор залишає за собою право обчислювати такі вирази у будь-якому порядку, навіть у разі, коли у виразі є дужки, що специфікують порядок обчислення.

У СП ТЗ реалізовано операцію унарного плюсу, що дозволяє гарантувати порядок обчислення виразів у дужках.

Операція послідовного обчислення, логічні операціїІ та АБО, умовна операція та операція виклику функції гарантують певний порядок обчислення своїх операндів. Операція послідовного обчислення забезпечує обчислення своїх операндів по черзі, зліва направо (кома, що розділяє аргументи у виклику функції, не є операцією послідовного обчислення і не забезпечує таких гарантій). Гарантується лише те, що на момент виклику функції всі аргументи вже обчислені.

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

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

int х, у, z, f();

z = x > у || f(x, у);

Спочатку обчислюється вираз х>у. Якщо воно істинно, змінної z присвоюється значення 1, а функція f не викликається. Якщо значення х не більше у, то обчислюється вираз f(x,y). Якщо функція f повертає ненульове значення, то змінній z надається 1, інакше 0. Відзначимо також, що при виклику функції f гарантується, що значення її першого аргументу більше другого.

Розглянутий приклад показує основні можливості використання порядку виконання логічних операцій. Це, по-перше, підвищення ефективності з допомогою приміщення найімовірніших умов перших операндів логічних операцій. По-друге, це можливість вставки у вираз перевірок, при помилковості яких наступні дії не будуть проводитися. Так, у наступному умовному операторі ifчитання чергового символу з файлу буде виконуватися лише в тому випадку, якщо кінець файлу ще не досягнуто:

if(!feof(pf)) && (З = getc (pf)) ...

Тут feof- функція перевірки на кінець файлу, getc- функція читання символу файлу (див. розділ 12).

По-третє, можна гарантувати, що у виразі f(x)&g(y)функція fбуде викликана раніше, ніж функція g. Для вираження f(x)+g(y)цього стверджувати не можна.

У наступних прикладах показано групування операндів для різних виразів.

Вираз Групування операндів
a&b || c (a & b) | c
a = b | c a = (b | | c)
q && r || s-- (q&&r) || (s--)
p == 0? p += 1: p += 2 (p == 0 ? p += 1: p) += 2

У першому прикладі порозрядна операція І (&) має більший пріоритет, ніж логічна операція АБО (||), тому вираз а&bє першим операндом логічної операції АБО.

У другому прикладі логічна операція АБО (||) має більший пріоритет, ніж операція простого присвоєння, тому вираз b||сутворює правий операнд операції присвоєння. (Зверніть увагу на те, що значення, яке надається а, є нуль чи одиниця.)

C++ для початківців

4.13. Пріоритети

Пріоритети операцій задають послідовність обчислень у складному вираженні.

Наприклад, яке значення набуде ival?

Int ival = 6+3*4/2+2;
Якщо обчислювати операції зліва направо, вийде 20. Серед інших можливих результатів будуть 9, 14 та 36. Правильна відповідь: 14. У С++ множення та розподіл мають більш високий пріоритет, ніж додавання, тому вони будуть обчислені раніше. Їхні власні пріоритети рівні, тому множення та розподіл будуть обчислюватися зліва направо. Таким чином, порядок обчисленняданого виразу

1. 3 * 4 => 12 2. 12 / 2 => 6 3. 6 + 6 => 12 4. 12 + 2 => 14

такий:

Наступна конструкція поводиться не так, як можна було б очікувати. Пріоритет операції присвоєння менший, ніж операції порівняння:

While (ch = nextChar() != "\n") Програміст хотів присвоїти змінній ch значення, а потім перевірити, чи воно символунового рядка
. Однак насправді вираз спочатку порівнює значення, отримане від nextChar(), з \n, і результат - true або false - присвоює змінної ch.

4 * 5 + 7 * 2 ==> 34 4 * (5 + 7 * 2) ==> 76 4 * ((5 + 7) * 2) ==> 96

Пріоритети операцій можна змінити за допомогою дужок. Вирази у дужках обчислюються насамперед. Наприклад:

Ось як за допомогою дужок виправити поведінку попереднього прикладу:

While ((ch = nextChar()) != "\n") Оператори мають іпріоритетом , іасоціативністю

. Оператор присвоювання правоасоціативний, тому обчислюється праворуч наліво:

Ival = jval = kva1 = lval
Спочатку kval набуває значення lval, потім jval – значення результату цього присвоювання, і зрештою ival набуває значення jval.

Арифметичні операції, навпаки, лівоасоціативні. Отже, у виразі

Ival + jval + kva1 + 1va1
спочатку складаються ival та jval, потім до результату додається kval, а потім і lval. У таблиці 4.4 наведенооператорів С++ у порядку зменшення їхнього пріоритету. Оператори всередині однієї секції таблиці мають рівні пріоритети. Всі оператори певної секції мають більший пріоритет, ніж оператори із секцій, що йдуть за нею. Так, операції множення і поділу мають однаковий пріоритет, і він вищий за пріоритет будь-якої з операцій порівняння.

Вправа 4.18

Який порядок обчислення таких виразів? У відповідь використовуйте таблицю 4.4.

(a) ! ptr == ptr->next (b) ~ uc ^ 0377 & ui<< 4 (c) ch = buf[ bp++ ] != "\n"

Вправа 4.19

Усі три висловлювання з попередньої вправи обчислюються над тій послідовності, яку, мабуть, хотів задати програміст. Розставте дужки так, щоб реалізувати початковий задум.

Вправа 4.20

Наступні висловлювання викликають помилку компіляції через неправильно зрозумілий пріоритет операцій. Поясніть, як виправити їх, використовуючи таблицю 4.4.

(a) int i = doSomething(), 0; (b) cout<< ival % 2 ? "odd" : "even";

Таблиця 4.4. Пріоритети операцій

Оператор Значення Використання
:: Глобальна область видимості ::name
:: Область видимості класу class::name
:: Область видимості простору імен namespace::name
. Доступ до члена object.member
-> Доступ до члена за вказівником pointer->member
Взяття індексу variable
() Виклик функції name(expr_list)
() Побудова значення type(expr_list)
++ постфіксний інкремент lvalue++
постфіксний декремент lvalue--
typeid ідентифікатор типу typeid(type)
typeid ідентифікатор типу виразу typeid(expr)
перетворення типу const_cast (expr)
перетворення типу dynamic_cast (expr)
reinterpret_cast приведення типу reinterpret_cast (expr)
static_cast приведення типу static_cast (expr)
sizeof розмір об'єкта sizeof expr
sizeof розмір типу sizeof(type)
++ префіксний інкремент ++lvalue
-- префіксний декремент --lvalue
~ побітове НЕ ~expr
! логічне НЕ !expr
- унарний мінус -expr
+ унарний плюс +expr
* розіменування *expr
& адреса &expr
() приведення типу (type)expr
new виділення пам'яті новий тип
new виділення пам'яті та ініціалізація новий тип (exprlist)
new Виділення пам'яті під масив всі форми
delete звільнення пам'яті всі форми
delete звільнення пам'яті з-під масиву всі форми
->* доступ до члена класу за вказівником pointer-> *pointer_to_member
.* доступ до члена класу за вказівником object.*pointer_to_member
* Розмноження expr * expr
/ Поділ expr / expr
% розподіл за модулем expr % expr
+ додавання expr + expr
- віднімання expr - expr
<< зрушення вліво expr<< expr
>> зрушення вправо expr >> expr
< менше expr< expr
<= менше або дорівнює expr<= expr
> більше expr > expr
>= більше або дорівнює expr >= expr
== одно expr == expr
!= не дорівнює expr! = expr
& побітове І expr & expr
^ побітове ВИКЛЮЧНЕ АБО expr ^ expr
| побітове АБО expr | expr
&& логічне І expr && expr
|| логічне АБО expr || expr
?: умовний оператор expr? expr * expr
= привласнення l-значення = expr
=, *=, /=, %=, +=, -=, <<=, >>=, &=, |=, ^= складове привласнення l-значення + = expr і т.д.
throw збудження виключення throw expr
, кома expr, expr

Щоб правильно обчислювати вирази (наприклад, 4 + 2 * 3), ми повинні знати, які оператори що означають та в якому порядку їх слід застосовувати. Ця послідовність, у якій вони виконуються, називається пріоритетом операцій. Дотримуючись звичайним правиламматематики (у якій множення слід виконувати перед додаванням), вираз вище вирішується так - 4 + (2 * 3), результат - значення 10.

У C++ всі оператори (операції) мають власний рівень пріоритету. Ті, в яких він вищий – виконуються першими. У таблиці нижче можна бачити, що пріоритет операцій множення та поділу (5) вищий, ніж в операціях складання та віднімання (6). Компілятор використовує це визначення порядку обробки виразів.

А що робити, якщо у двох операторів у вираженні однаковий рівень пріоритету і вони розміщені поруч? Яку операцію виконувати першою? А тут уже компілятор користуватиметься правилами асоціативності,які вказують напрямок виконання операцій: зліва направо або праворуч наліво. Наприклад, у 3*4/2, операції множення та поділу мають однаковий рівень пріоритету – 5. А асоціативність 5 рівня – зліва направо, так що вирішуватимемо так: (3*4)/2 = 6.

Таблиця пріоритету операцій

Примітки:

1 – це найвищий рівень пріоритету, а 17 – найнижчий. Операції з більш високим рівнемпріоритети виконуються першими.

L -> R означає зліва направо.

R -> L означає праворуч наліво.

Асоціативність Оператор Опис приклад
1. Ні :: Глобальна область видимості (унарний) ::name
:: Область видимості класу (бінарний) class_name::member_name
2. L->R () Круглі дужки (expression)
() Виклик функції function_name(parameters)
() Ініціалізація type name(expression)
{} Uniform ініціалізація (C++11) type name(expression)
type() Functional cast new_type(expression)
type() Functional cast (C++11) new_type(expression)
Індекс масиву pointer
. Доступ до члена об'єкту object.member_name
-> Доступ до члена об'єкта через покажчик object_pointer->member_name
++ Пост-інкремент lvalue++
–– Пост-декремент lvalue––
typeid Інформація про тип під час виконання typeid(type) або typeid(expression)
const_cast Cast away const const_cast(expression)
dynamic_cast Run-time type-checked cast dynamic_cast(expression)
reinterpret_cast Cast one type to another reinterpret_cast(expression)
static_cast Compile-time type-checked cast static_cast(expression)
3. R->L + Унарний плюс +expression
Унарний мінус -expression
++ Пре-інкремент ++lvalue
–– Пре-декремент ––lvalue
! Логічне НЕ (NOT) !expression
~ Побітове НЕ (NOT) ~expression
(type) C-style cast (new_type)expression
sizeof Розмір у байтах sizeof(type) or sizeof(expression)
& Адреса &lvalue
* Dereference *expression
new Динамічне виділення пам'яті новий тип
new Динамічний розподіл масиву новий тип
delete Динамічне видалення пам'яті delete pointer
delete Динамічне видалення масиву delete pointer
4. L->R ->* Member pointer selector object_pointer->*pointer_to_member
.* Member object selector object.*pointer_to_member
5. L->R * Розмноження expression * expression
/ Поділ expression / expression
% Залишок expression % expression
6. L->R + Додавання expression + expression
Віднімання expression - expression
7. L->R << Побітове зрушення вліво expression<< expression
>> Побітове зрушення вправо expression >> expression
8. L->R < Порівняння. Менше ніж expression< expression
<= Порівняння. Менше ніж чи одно expression<= expression
> Порівняння. Більше ніж expression > expression
>= Порівняння. Більш ніж чи одно expression >= expression
9. L->R == Рівно expression == expression
!= Не дорівнює expression != expression
10. L->R & Побітове І (AND) expression & expression
11. L->R ^ Побітове що виключає АБО (XOR) expression ^ expression
12. L->R | Побітове АБО (OR) expression | expression
13. L->R && Логічне І (AND) expression && expression
14. L->R || Логічне АБО (OR) expression || expression
15. R->L ?: Тернарний оператор (див. примітку нижче) expression? expression: expression
= Привласнення lvalue = expression
*= Множення з присвоєнням lvalue *= expression
/= Поділ із присвоєнням lvalue /= expression
%= Поділ із залишком із присвоєнням lvalue %= expression
+= Додавання з привласненням lvalue += expression
-= Віднімання з присвоєнням lvalue -= expression
<<= Привласнення з побитовим зрушенням вліво lvalue<<= expression
>>= Привласнення з побитовим зрушенням праворуч lvalue >>= expression
&= Привласнення з побітовою операцією І (AND) lvalue &= expression
|= Привласнення з побітовою операцією АБО (OR) lvalue |= expression
^= Привласнення з побітовою операцією «що виключає АБО» (XOR) lvalue ^= expression
16. R->L throw Створення виключення вручну throw expression
17. L->R , Оператор Comma (кома) expression, expression

Примітка: Вираз у середині умовного оператора?: виконується ніби воно знаходилося в круглих дужках.

Деякі оператори ви вже знаєте: +, -, *, /, (), =,<,>, <= и >=. Їх значення однакові як і математиці, і у C++.

Однак, якщо у вас немає досвіду роботи з іншими мовами програмування, більшість цих операторів вам зараз незрозумілі. Це нормально. Ми розглянемо більшу частину з них у цьому розділі, а про інших розповімо за необхідності.

Ця таблиця призначена в першу чергу для того, щоб ви могли будь-якої миті звернутися до неї для вирішення можливих проблемпріоритету чи асоціативності.

Як зводити в ступінь C++?

Ви вже повинні були помітити, що оператор ^, який зазвичай використовується для позначення зведення у ступінь у звичайній математиці, не є таким C++. У С++ це побітова операція XOR. То що тоді замість ^? А натомість – функція pow(), яка знаходиться в заголовному файлі :

#include double x = pow (3.0, 4.0); // 3 ступінь 4

#include

double x = pow (3.0, 4.0); // 3 ступінь 4

Зверніть увагу, параметри та значення функції pow() — типу double. А оскільки типи з плаваючою точкою відомі помилками округлення, то результати pow() можуть бути трохи неточними (трохи менше або трохи більше).

Якщо вам потрібно звести в ступінь ціле число, краще використовувати власну функцію, наприклад:

// примітка: експонент не повинен бути негативним int pow(int base, int exp) ( int result = 1; while (exp) ( if (exp & 1) result *= base; exp >>= 1; base *= base ; ) return result;

// Примітка: експонент не повинен бути негативним

int pow (int base, int exp)

int result = 1;

while (exp )

if (exp & 1)

result * = base;

exp >> = 1;

base * = base;

return result;

Тут використовується алгоритм «Зведення у ступінь шляхом зведення у квадрат».

Не хвилюйтеся, якщо щось не зрозуміло. Просто пам'ятайте про проблему переповнення, яка може статися, якщо один із аргументів буде занадто великим.

Тест

1) З шкільної математикиви знаєте, що вирази усередині дужок виконуються першими. Наприклад, в (2 + 3) * 4 частина (2 + 3) буде виконуватися першою.

У цьому завданні є 4 вирази, в яких відсутні дужки. Використовуючи пріоритет операцій та правила асоціативності в таблиці вище, додайте дужки у кожен вираз так, якби їх обробляв компілятор.

Підказка: Використовуйте колонку прикладу таблиці вище, щоб визначити, чи оператор унарним (має один операнд) чи бінарним (два операнда). Якщо забули, що таке унарний чи бінарний — дивіться урок 17.

Приклад рішення: х = 2 + 3% 4

Бінарний оператор % має вищий пріоритет, ніж оператор + чи =, тому він застосовується першим: х = 2 + (3 % 4);

Бінарний оператор + має більший пріоритет, ніж =, тому наступним застосовується він.

Завдання

а) x = 3+4+5;
б) x = y = z;
в) z * = ++ y + 5;
г) a || b&&c || d;

Відповідь

а)Рівень пріоритету бінарного оператора+ вище, ніж у =:

х = (3+4+5);

Асоціативність бінарного оператора + зліва направо:

Відповідь: х = ((3 + 4) + 5).

б)Асоціативність бінарного оператора = справа наліво:

Відповідь: x = (y = z).

в)Унарний оператор ++ має найвищий пріоритет:

Бінарний оператор + має другий найвищий пріоритет:

Відповідь: z * = ((++ y) + 5).

г)Бінарний оператор && має більший пріоритет, ніж ||:

a || (b&&c) || d;

Асоціативність бінарного оператора зліва направо:

Відповідь: (a || (b && c)) || d.

Порядок виконання операцій при обчисленні значення виразу визначається розташуванням знаків операцій, круглих дужокі пріоритетом операцій . Операції з найвищим пріоритетом виконуються насамперед. Якщо у виразі міститься кілька операцій одного пріоритету одному й тому рівні, їх обробка проводиться відповідно до порядком виконання – справа наліво чи зліва направо. Якщо необхідно змінити порядок виконання операцій у виразі, слід використовувати круглі дужки, наприклад (x + y) * z .

Пріоритет операції команижче, ніж у решти операцій.

У наведеній нижче таблиці операції мови C++ наведено в порядку зменшення пріоритету. Операції з різними пріоритетами розділені межею.

Таблиця пріоритетів операцій

Знаки операцій

Назви операцій

Порядок виконання

підвищення пріоритету

постфіксний інкремент

постфіксний декремент

зліва направо

sizeof

(тип ) вираз та

тип (вираз)

розмір операнда в байтах

префіксний інкремент

префіксний декремент

порозрядне НЕ

логічне НЕ

унарні мінус, плюс

перетворення типу

справаліворуч

множення

залишок від поділу цілих

зліва направо

додавання

віднімання

зліва направо

зрушення вліво

зрушення вправо

зліва направо

менше або дорівнює

більше або дорівнює

зліва направо

зліва направо

порозрядне І

зліва направо

порозрядне виключне АБО

зліва направо

порозрядне АБО

зліва направо

логічне І

зліва направо

логічне АБО

зліва направо

? :

умовна

справаліворуч

*= , /= , %=

+= , - =

<<= , >>=

&= , |= , ^=

присвоєння (просте та

складова)

справаліворуч

операція кома

зліва направо

Приведення (перетворення) типу

Мова програмування С++, будучи типізованим мовою, дозволяє дуже вільно поводитися з висловлюваннями, оперуючими різними типами даних. І тут операнди висловлювання наводяться до деякого загального типу.

Автоматично виробляються лише перетворення, які перетворюють операнди з меншим діапазоном значень операнди з великим діапазоном значень, оскільки це відбувається без втрати інформації. Наприклад, якщо у виразі ival + fvalзмінна ival типу int , а змінна fval– типу float , то при виконанні операції(+ ) значення змінної ivalбуде наведено до типу float .

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

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

(тип) вираз

тип(вираз)

Операндом операціїприведення типує вираз, що перетворюється. Пріоритет операції приведення типутакий самий, як і в інших унарних операцій. Наприклад: (longdouble) 5; (int) f ; (double) a/2 .

Якщо вираз, що розглядається, має досить складний вигляд, бажано брати його в дужки, щоб переконатися, що тип буде змінений у результату всього виразу, а не у його частини. Наприклад,

(int) x + b * c

(int) (x + b * c )

У першому випадку перетворення відноситься до змінної x , у другому – до всього виразу x+ b * c.

Пріоритет та порядок виконання

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

У таблиці 4.1 наведено операції у порядку зменшення пріоритету. Операції, розташовані в одному рядку таблиці або об'єднані в одну групу, мають однаковий пріоритет і однакову асоціативність.

Таблиця 4.1.

Пріоритет та асоціативність операцій у мові Сі

Знак операції Найменування Асоціативність
() . -> Первинні Зліва направо
+ - ~! * & ++ - sizeof приведення типу Унарні Справа наліво
* / % Мультиплікативні Зліва направо
+ - Адитивні Зліва направо
>> << Зрушення Зліва направо
< > <= >= Ставлення Зліва направо
== != Ставлення Зліва направо
& Порозрядне І Зліва направо
^ Порозрядне виключне АБО Зліва направо
| Порозрядне, що включає АБО Зліва направо
&& Логічне І Зліва направо
|| Логічне АБО Зліва направо
?: Умовна Справа наліво
= *= /= %= += -= <<= >>= &= |= ^= Просте та складове привласнення Справа наліво
, Послідовне обчислення Зліва направо

З таблиці 4.1. слід, що операнди, що представляють виклик функції, індексний вираз, вираз вибору елемента і вираз у дужках мають найбільший пріоритет і асоціативність зліва направо. Приведення типу має той самий пріоритет і порядок виконання, як і унарні операції.

Вираз може містити кілька операцій одного пріоритету. Коли кілька операцій однієї й тієї ж рівня пріоритету виявляються у виразі, всі вони застосовуються відповідно до їх асоціативністю - або праворуч наліво, або зліва направо.

Слід зазначити, що у мові Сі прийнято невдалий порядок пріоритету деяких операцій, зокрема операції зсуву і порозрядних операцій. Вони мають нижчий пріоритет, ніж арифметичні операції (додавання та ін.). Тому вираз

а = b & 0xFF + 5

обчислюється як

а = b & (0xFF + 5),

а вираз

а+с >> 1

обчислюється як

(а+с) >> 1

Мультиплікативні, адитивні та порозрядні операції мають властивість комутативності. Це означає, що результат обчислення виразу, що включає кілька комутативних операцій однієї й тієї ж пріоритету, залежить від порядку виконання цих операцій. Тому компілятор залишає за собою право обчислювати такі вирази у будь-якому порядку, навіть у разі, коли у виразі є дужки, що специфікують порядок обчислення.

У СП ТЗ реалізовано операцію унарного плюсу, що дозволяє гарантувати порядок обчислення виразів у дужках.

Операція послідовного обчислення, логічні операції І та АБО, умовна операція та операція виклику функції гарантують певний порядок обчислення своїх операндів. Операція послідовного обчислення забезпечує обчислення своїх операндів по черзі, зліва направо (кома, що розділяє аргументи у виклику функції, не є операцією послідовного обчислення і не забезпечує таких гарантій). Гарантується лише те, що на момент виклику функції всі аргументи вже обчислені.

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

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

int х, у, z, f();

z = x > у || f(x, у);

Спочатку обчислюється вираз х>у. Якщо воно істинно, змінної z присвоюється значення 1, а функція f не викликається. Якщо значення х не більше у, то обчислюється вираз f(x,y). Якщо функція f повертає ненульове значення, то змінній z надається 1, інакше 0. Відзначимо також, що при виклику функції f гарантується, що значення її першого аргументу більше другого.

Розглянутий приклад показує основні можливості використання порядку виконання логічних операцій. Це, по-перше, підвищення ефективності з допомогою приміщення найімовірніших умов перших операндів логічних операцій. По-друге, це можливість вставки у вираз перевірок, при помилковості яких наступні дії не будуть проводитися. Так, у наступному умовному операторі ifчитання чергового символу з файлу буде виконуватися лише в тому випадку, якщо кінець файлу ще не досягнуто:

if(!feof(pf)) && (З = getc (pf)) ...

Тут feof- функція перевірки на кінець файлу, getc- функція читання символу файлу (див. розділ 12).

По-третє, можна гарантувати, що у виразі f(x)&g(y)функція fбуде викликана раніше, ніж функція g. Для вираження f(x)+g(y)цього стверджувати не можна.

У наступних прикладах показано групування операндів для різних виразів.

Вираз Групування операндів
a&b || c (a & b) | c
a = b | c a = (b | | c)
q && r || s-- (q&&r) || (s--)
p == 0? p += 1: p += 2 (p == 0 ? p += 1: p) += 2

У першому прикладі порозрядна операція І (&) має більший пріоритет, ніж логічна операція АБО (||), тому вираз а&bє першим операндом логічної операції АБО.

У другому прикладі логічна операція АБО (||) має більший пріоритет, ніж операція простого присвоєння, тому вираз b||сутворює правий операнд операції присвоєння. (Зверніть увагу на те, що значення, яке надається а, є нуль чи одиниця.)

У третьому прикладі показано синтаксично коректний вираз, який може виробити несподіваний результат. Логічна операція І (&&) має вищий пріоритет, ніж логічна операція АБО (||), тому запис q&&rутворює операнд. Оскільки логічні операції спочатку обчислюють свій лівий операнд, то вираз q&&rобчислюється раніше, ніж s--. Однак якщо q&&rдає ненульове значення, то s--не буде обчислюватися та sне декрементується. Більш надійно було б помістити s--на місце першого операнда виразу або декрементувати sокремою операцією.

У четвертому прикладі показано неправильне вираз, що призведе до помилки під час компіляції. Операція рівності (==) має найбільший пріоритет, тому p==0групується в операнд. Тернарна операція ?: має наступний пріоритет. Її першим операндом є вираз p==0, другим операндом - вираз p+=1. Проте останнім операндом тернарної операції вважатиметься p, а не p+=2. так як у даному випадкуідентифікатор pза пріоритетом операцій пов'язаний більш тісно з тернарною операцією, ніж зі складовою операцією додавання з присвоєнням. В результаті виникає синтаксична помилка, Оскільки лівий операнд складової операції присвоєння не є L-виразом.

Щоб попередити подібні помилки і зробити програму більш наочною, рекомендується використовувати дужки. Попередній приклад може бути коректно оформлений таким чином:

(Р == 0)? (р + = 1): (р + = 2)

З книги ПРОГРАМНЕ ЗАБЕЗПЕЧЕННЯ ВБУДОВАНИХ СИСТЕМ. Загальні вимогидо розробки та документування автора Держстандарт Росії

З книги Delphi. Вчимося на прикладах автора Паризький Сергій Михайлович

Порядок виконання операторів складних виразахоператори виконуються у такому порядку:1. ().2. not.3. *, /, div, mod, and, shl, shr, as.4. +, -, or, xor.5. =,<>, <, >, <=, >=, in,

З книги Windows Script Host для Windows 2000/XP автора Попов Андрій Володимирович

Порядок виконання операторів У табл. П1.10 оператори мови JScript розташовані за старшинством, тобто. у складових операторах першими виконуватимуться ті їх, які стоять у цій таблиці вище. Якщо оператори розташовані в одному рядку таблиці, то вони виконуються ліворуч

З книги UNIX: взаємодія процесів автора Стівенс Вільям Річард

9.6. Пріоритет читання та запису У нашій реалізації блокувань читання-запису в розділі 8.4 пріоритет надавав процесам, що очікують запису. Тепер ми вивчимо деталі можливого рішеннязавдання читачів та письменників за допомогою блокування записів fcntl. Хочеться дізнатися, як

З книги TCP/IP Архітектура, протоколи, реалізація (включаючи IP версії 6 та IP Security) автора Фейт Сідні М

6.13.4 Пріоритет та тип обслуговування Початковим спонсором набору протоколів TCP/IP було Міністерство оборони США, для якого було важливим завдання пріоритетів датаграм. Пріоритети мало використовуються поза військовими та урядовими організаціями. Для пріоритету

З книги HTML 5, CSS 3 та Web 2.0. Розробка сучасних веб-сайтів. автора Дронов Володимир

22.6.1 Пріоритет Поле Priority виконує дві функції. При керуванні навантаженням для трафіку TCP великим номерам відповідають пакети керування та інтерактивний трафік, а меншим номерам - звичайний трафік. Визначено такі значення:0 Трафік не специфікований1 Заповнюючий

З книги HTML 5, CSS 3 та Web 2.0. Розробка сучасних Web-сайтів автора Дронов Володимир

З книги QNX/UNIX [Анатомія паралелізму] автора Цилюрик Олег Іванович

Пріоритет операторів Останнім питанням, яке ми тут розберемо, є пріоритет операторів. Як ми пам'ятаємо, пріоритет впливає на порядок, в якому виконуються оператори у виразі. Нехай є такий вираз: a = b + c - 10;

З книги Firebird КЕРІВНИЦТВО РОЗРОБНИКА БАЗ ДАНИХ автора Боррі Хелен

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

З книги Мова Сі - посібник для початківців автора Прата Стівен

Пріоритет операторів Пріоритет визначає порядок, в якому оператори і створювані ними значення обчислюються у виразі.

З книги C++ для початківців автора Ліппман Стенлі

Порядок виконання операцій Розглянемо наступний рядок: butter = 25.0 + 60.0 * n/SCALE; У цьому операторі є операції складання, множення та поділу. Яку операцію буде виконано першою? Чи складатиметься 25.0 з 60.0, потім результат 85.0 множитиметься на n, а твір

З книги Розробка ядра Linux автора Лав Роберт

1.2.1. Порядок виконання інструкцій За промовчанням інструкції програми виконуються одна за одною, послідовно. У програмі int main()(readIn();sort();compact();print();return 0;)першою буде виконана інструкція readIn(), за нею sort(), compact() і нарешті print(). уявімо собі ситуацію, коли

З книги Опис мови PascalABC.NET автора Колектив РуБоард

Пріоритет процесу Найбільш поширеним типом алгоритмів планування є планування з управлінням пріоритетами (priority-based). Ідея полягає в тому, щоб розмістити процеси по порядку відповідно до їх важливості та необхідності використання

З книги автора

Бар'єри та порядок виконання У разі, коли необхідно мати справу з синхронізацією між різними процесорамиабо різними апаратними пристроями, іноді виникає вимога, щоб читання пам'яті (load) або запис у пам'ять (save) виконувались у тому порядку, як і

З книги автора

Порядок виконання операцій процесором Згадайте з матеріалу глави 9, "Засоби синхронізації в ядрі", що для різних апаратних платформ процесори різного ступенязмінюють порядок виконання програмних інструкцій. Для деяких процесорів порядок виконання

З книги автора

Пріоритет операцій Пріоритет визначає порядок виконання операцій у виразі. Першими виконуються операції, які мають найвищий пріоритет. Операції, що мають однаковий пріоритет, виконуються зліва направо. Таблиця пріоритетів операцій @, not, ^, +, - (унарні),