Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Мова програмування С.docx
Скачиваний:
3
Добавлен:
01.05.2025
Размер:
490 Кб
Скачать
☆

2.10 Оператори та вирази присвоєння

Вираз на кшталт

i = i + 2

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

i += 2

Оператор += також називається оператором присвоєння. Більшість бінарних операторів (такі як +, що має лівий і правий операнд) мають відповідний оператор присвоєння op=, де op може бути одним з наступних

+ - * / % << >> & ^ |

Якщо expr1 і expr2 — це два вирази, тоді

expr1 op= expr2

еквівалентний

expr1 = (expr1) op (expr2)

крім випадку, коли expr1 обчислюється тільки один раз. Зверніть увагу на дужки навколо expr2:

x *= y + 1

означає

x = x * (y + 1)

замість

x = x * y + 1

В якості прикладу наведемо функцію bitcount, яка обчислює кількість 1-бітів в своєму аргументі-цілому.

/* bitcount: рахує 1-біти в x */

int bitcount(unsigned x)

{

int b;

for (b = 0; x != 0; x >>= 1)

if (x & 01)

b++;

return b;

}

Оголошення аргументу x як unsigned (беззнакового) гарантує, що коли його буде зміщено вправо, звільнені біти заповняться нулями, а не знаковими бітами, незалежно від машини на якій було запущено програму.

Крім стислості, оператори присвоєння мають переважають тим, що вони краще відповідають способу мислення людей. Ми кажемо «додати 2 до i» або «збільшити i на 2», а не «взяти i, додати 2, а потім помістити результат назад у i». Тому виразу i += 2 надається перевага над i = i+2. На додаток, у складних виразах на зразок

yyval[yypv[p3+p4] + yypv[p1]] += 2

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

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

while ((c = getchar()) != EOF)

...

Інші оператори присвоєння (+=, -= тощо) також можуть зустрічатися всередині виразів, хоч і не так часто.

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

Вправа 2-9. У двійковій числовій системі (two's complement number system), x &= (x-1)вилучає крайній правий біт з x. Поясніть чому. Скористайтеся з цього спостереження для написання швидшої версії bitcount.

2.11 Вирази умов

Вирази на зразок

if (a > b)

z = a;

else

z = b;

обчислюють z як найбільше значення з-поміж a та b. Умовний вираз із використанням трійчастого оператора «?:» дають альтернативний спосіб написання подібної конструкції. У виразі

expr1 ? expr2 : expr3

вираз expr1 розглядається першим. Якщо expr1 ненульовий (істина), тоді обчислюється expr2, і це й буде кінцевим значенням цілого виразу умови. У протилежному випадку, обчислюється expr3, і він стане кінцевим значенням. Оцінюється тільки один із expr2 та expr3. Таким чином, щоб встановити z до максимального значення a або b, ми напишемо

z = (a > b) ? a : b; /* z = max(a, b) */

Слід зауважити, що вираз умови — це дійсно вираз, і може бути використаний там де будь-який інший. Якщо expr2 і expr3 — різних типів, тип результату визначається правилами перетворення, обговорених раніше в цьому розділі. Наприклад, якщо f має тип float, а n — це int, тоді вираз

(n > 0) ? f : n

буде типу float, незалежно від того, чи n додатній.

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

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

for (i = 0; i < n; i++)

printf("%6d%c", a[i], (i%10==9 || i==n-1) ? '\n' : ' ');

Символ нового рядка виводиться після кожного десятого елемента і після n-нного. За рештою елементів слідує пробіл. Це може здаватися складним, але воно компактніше ніж еквівалент ізif-else. Іншим хорошим прикладом є

printf("You have %d items%s.\n", n, n==1 ? "" : "s");

Вправа 2-10. Перепишіть функцію lower, яка обертає літери верхнього регістру на нижній, за використанням виразу умови замість if-else.