Оператор присвоюванняПрисвоєння (англ. assignment) — механізм в програмуванні, що дозволяє динамічно змінювати зв'язки об'єктів даних (зазвичай, змінних) з їхніми значеннями. Строго кажучи, зміна значень є побічним ефектом операції присвоєння, і в багатьох сучасних мовах програмування сама операція також повертає певний результат (як правило, копію присвоєного значення). На фізичному рівні результат операції присвоєння полягає в проведенні запису і перезапису фрагментів пам'яті або регістрів процесора. Присвоєння — одна з центральних конструкцій в імперативних мовах програмування, ефективно і просто реалізується на фон-Нейманівській архітектурі, яка лежить в основі сучасних комп'ютерів. В логічному програмуванні прийнято інший, алгебраїчний підхід. Звичайного («деструктивного») присвоєння тут немає. Існують тільки невідомі, які ще не обчислені, і відповідні ідентифікатори для позначення цих невідомих. Програма тільки визначає їхні значення, самі вони сталі. Звичайно, в реалізації програма робить запис в пам'ять, але мови програмування цього не відображають, даючи програмісту можливість працювати з ідентифікаторами постійних значень, а не зі змінними. В чистому функційному програмуванні не використовують змінні, тому явний оператор присвоєння не потрібен. Визначення присвоєнняЗагальний синтаксис простого присвоєння такий: <вираз зліва> <оператор присвоєння> <вираз справа> Результатом обчислення «Вираз зліва» має бути місце розташування об'єкта даних, або цільова змінна, ідентифікатор комірки пам'яті, куди буде здійснено запис. Такі посилання називаються «лівостороннім значеннями» (англ. lvalue). Типові приклади лівостороннього значення:
Нижче буде наведено складніші приклади. «Вираз справа» має позначати в той чи інший спосіб величину, яку буде присвоєно об'єктові даних. Таким чином, навіть якщо в правій частині ім'я тієї ж змінної, що і ліворуч, інтерпретується воно інакше — такі посилання називаються «правостороннє значення» (англ. rvalue). Подальші обмеження на вираз накладає використана мова: так, в статично типізованих мовах воно повинно мати той же тип, що і цільова змінна, або тип, що можна привести до нього; в деяких мовах (наприклад, Сі або Python) у вираз може входити також інша операція присвоєння Оператором присвоєння в мовах програмування найчастіше виступають set <цільова_змінна> <вираз> Цей запис еквівалентний виклику функції. Аналогічно, в Коболі старого стилю: MULTIPLY 2 BY 2 GIVING FOUR. Алгоритм роботи оператора присвоєння
Символ присвоєнняВибір символу присвоєння викликає суперечки серед розробників мов. Існує думка, що використання символу Так, Ніклаус Вірт стверджував[1] :
Вибір символу оператора рівності в мові при використанні
Запис рівності у мові C
Наприклад, у виразі мовою PL/I: А = В = С змінній Семантичні особливостіВ імперативних мовах не завжди спосіб інтерпретації присвоєння «інтуїтивний», єдино вірний і можливий. В імперативних мовах іноді неможливо зрозуміти за використовуваним синтаксисом як реалізується семантика присвоєння, якщо це явно не визначено в мові. Наприклад, у мові Forth використовується присвоювання значення, коли дані між операціями, проходять через стек даних, при цьому сама операція не є покажчиком на дані, а лише виконує дії визначені операцією. Унаслідок можна зробити присвоювання даних, сформованих (розташованих) далеко від операції присвоєння. Приклад для сказаного вище: \ Визначення змінної AAA і наступним рядком присвоєння їй значення 10 VARIABLE AAAA 10 AAA! або так те ж саме (семантично): 10 VARIABLE AAA AAA! Неоднозначність присвоєнняРозглянемо приклад: X = 2 + 1 Це можна зрозуміти як «результат обчислення 2+1 (тобто 3) присвоюється змінній X is 2 + 1, X = 3 X = 2 + 1, X = 3 Перша послідовність буде визнана істинною, друга — хибною. Семантика посиланьПри роботі з об'єктами великих розмірів і складної структури багато мов використовують так звану «семантику посилань». Це означає, що присвоєння в класичному розумінні не відбувається, але вважається, що значення цільової змінної розташовується на тому ж місці, що і значення вихідної. Наприклад (Python): a = [1, 2, 3] b = a a [1] = 1000 Після цього Підміна операціїБагато мов надають можливість змінювати сенс присвоєння: або через механізм властивостей, або через перевантаження оператора присвоєння. Підміна може знадобиться для виконання перевірок на допустимість присвоюється значення або будь-яких інших додаткових операцій. Перевантаження оператора присвоєння часто використовується для забезпечення «глибокого копіювання», тобто копіювання значень, а не посилань, які в багатьох мовах копіюються за замовчуванням. Такі механізми дозволяють забезпечити зручність при роботі, оскільки для програміста нема різниці між використанням вбудованого оператора і перевантаженого. З цієї ж причини можливі проблеми, тому що дії перевантаженого оператора можуть бути абсолютно відмінні від дій оператора за замовченням, а виклик функції не очевидний і легко може бути прийнятий за вбудовану операцію. Розширення конструкції присвоєнняОскільки операція присвоєння широко використовується, розробники мов програмування намагаються розробити нові конструкції для спрощеного запису типових операцій (додати в мову так званий «синтаксичний цукор»). Крім цього, в низькорівневих мовах програмування часто критерієм включення операції є можливість компіляції в ефективний виконуваний код.[2] Особливо відома цією властивістю мова Сі. Множинні цільові об'єктиОднією з альтернатив простого оператора є можливість присвоєння значення виразу декільком об'єктам. Наприклад, у мові PL/I оператор SUM, TOTAL = 0 одночасно присвоює нульове значення змінним SUM, TOTAL: Integer: = 0; Аналогічне присвоєння в мові Python має такий синтаксис: sum = total = 0 На відміну від PL/I, Ada та Python, де множинне присвоєння вважається тільки скороченою формою запису, в мовах C, Lisp та інших цей синтаксис має строгу основу: просто оператор присвоєння повертає присвоєне ним значення (див. вище). Таким чином, останній приклад — це насправді: sum = (total = 0) Рядок такого виду спрацює в Сі (якщо додати крапку з комою в кінці), але викличе помилку в Python. Паралельне присвоєнняДля деяких мов, наприклад Ruby та Python, підтримують розширений синтаксис присвоєння, який називається паралельним присвоєнням: a, b = 1, 11 Вважається, що таке присвоєння виконується одночасно і паралельно, що дозволяє коротко реалізувати за допомогою такої конструкції операцію обміну значень двох змінних.
Деякі мови (наприклад, PHP) мають конструкції, що дозволяють зімітувати паралельне присвоювання: list ($ a, $ b) = array ($ b, $ a); Умовне присвоєнняДеякі мови програмування, наприклад, C++ і Java, дозволяють умовне присвоєння. Наприклад, вираз:
Інший варіант умовного присвоєння (Ruby): a || = 10 Дана конструкція присвоює змінній Складені оператори присвоєнняСкладений оператор присвоєння дозволяє скорочено задавати часто використовувану форму присвоєння. За допомогою цього способу можна скоротити запис присвоєння, при якому цільова змінна використовується як перший операнд в правій частині виразу, наприклад: а = а + b Синтаксис складного оператора присвоєння мови Сі є об'єднанням потрібного бінарного оператора і оператора
У мовах програмування, що підтримують складені оператори (C++, C#, Python, Java та інші), звичайно існують версії для більшості бінарних операторів цих мов Унарні оператори присвоєнняУ мові програмування С і більшості похідних від неї присутні два спеціальних унарних (тобто мають один аргумент) арифметичних оператора, які насправді є скороченим присвоєнням. Ці оператори поєднують операції збільшення та зменшення на одиницю з присвоєнням. Оператори Нижче наведений приклад використання оператора інкременту для формування завершеного оператора присвоєння
Хоч це і не виглядає присвоєнням, але є ним. Результат виконання наведеного вище оператора рівнозначний результату виконання присвоєння. Оператори інкременту і декременту в мові Сі часто є скороченим записом для формування виразів, що містять індекси масивів. РеалізаціяРобота сучасних комп'ютерів складається зі зчитування даних з пам'яті в регістри, виконання операцій над цими даними і запису в пам'ять. Основною операцією тут є передача даних (з регістрів в пам'ять, з пам'яті в регістр, з регістра в регістр). Відповідно, вона виражається безпосередньо командами сучасних процесорів. Так, для архітектури x86 (усі наведені нижче команди відносяться також до даної архітектурі) це операція mov eax, [ebp-4] # Завантажити 32-бітне значення з пам'яті
mov [ebp+8], eax # Записати це значення за іншою адресою
Примітки
Див. такожЛітература
|
Portal di Ensiklopedia Dunia