Це не визначено, оскільки воно змінюється x
двічі між точками послідовності. Стандарт говорить, що він не визначений, тому він не визначений.
Стільки я знаю.
Але чому?
Я розумію, що заборона цього дозволяє компіляторам краще оптимізувати. Це могло мати сенс, коли винайдено С, але зараз це здається слабким аргументом.
Якби ми сьогодні винаходили C, чи зробили б це так, чи це можна зробити краще?
Чи, можливо, існує глибша проблема, яка ускладнює визначення послідовних правил для таких виразів, тому краще заборонити їх?
Отже, припустимо, ми повинні були винаходити C сьогодні. Я хотів би запропонувати прості правила для таких виразів x=x++
, які, здається, працюють краще, ніж існуючі правила.
Я хотів би отримати вашу думку щодо запропонованих правил порівняно з існуючими чи іншими пропозиціями.
Рекомендовані правила:
- Між точками послідовності не визначений порядок оцінювання.
- Побічні ефекти відбуваються негайно.
Немає жодної невизначеної поведінки. Вирази оцінюють до цього чи іншого значення, але, безумовно, не форматуватимуть ваш жорсткий диск (як не дивно, я ніколи не бачив реалізації, де x=x++
формати жорсткого диска).
Приклади виразів
x=x++
- Добре визначений, не змінюєтьсяx
.
Спочаткуx
збільшується (одразу, колиx++
оцінюється), потім зберігається старе значенняx
.x++ + ++x
- Збільшенняx
вдвічі, оцінюється до2*x+2
.
Хоча будь-яка сторона може бути оцінена спочатку, результат є абоx + (x+2)
(перший лівий бік), або(x+1) + (x+1)
(правий перший спочатку).x = x + (x=3)
- Неx
визначено , встановленоx+3
або6
.
Якщо права сторона оцінюється спочатку, то цеx+3
. Можливо також, щоx=3
оцінюється спочатку, так що це3+3
. У будь-якому випадкуx=3
присвоєння відбувається негайно приx=3
оцінці, тому збережене значення переписується іншим завданням.x+=(x=3)
- Добре визначено, встановлюєтьсяx
6.
Ви можете стверджувати, що це лише стенограма для виразу вище.
Але я б сказав, що він+=
повинен бути виконаний післяx=3
, а не у двох частинах (читатиx
, оцінюватиx=3
, додавати та зберігати нове значення).
Яка перевага?
Деякі коментарі підняли цю хорошу точку.
Я, звичайно, не думаю, що такі вирази, як вони, x=x++
слід використовувати в будь-якому звичайному коді.
Насправді я набагато суворіший за це - я вважаю, що єдине корисне використання x++
як в x++;
поодинці.
Однак я вважаю, що мовні правила повинні бути максимально простими. Інакше програмісти просто їх не розуміють. правило, яке забороняє двічі змінювати змінну між точками послідовності, безумовно, правило, яке більшість програмістів не розуміє.
Дуже основне правило таке:
Якщо A дійсне, а B - дійсне, і вони об'єднані в дійсний спосіб, результат є дійсним.
x
є дійсним значенням L, x++
є дійсним виразом і =
є коректним способом поєднання значення L та виразу, тож як x=x++
це не законно?
Стандарт C робить тут виняток, і цей виняток ускладнює правила. Ви можете шукати stackoverflow.com і бачити, наскільки цей виняток бентежить людей.
Тому я кажу - позбудьтеся цієї плутанини.
=== Підсумок відповідей ===
Навіщо це робити?
Я намагався пояснити в розділі вище - я хочу, щоб правила C були простими.Потенціал для оптимізації:
це вимагає деякої свободи від компілятора, але я не бачив нічого, що переконувало б мене, що це може бути значним.
Більшість оптимізацій все-таки можна зробити. Наприклад,a=3;b=5;
можна переупорядкувати, навіть якщо стандарт визначає порядок. Такі вирази, як іa=b[i++]
раніше, можна оптимізувати аналогічно.Ви не можете змінити існуючий стандарт.
Я визнаю, я не можу. Я ніколи не думав, що можу насправді йти вперед і змінювати стандарти та компілятори. Мені хотілося подумати, якби все можна було зробити інакше.
x
себе, і якщо ви хочете збільшити,x
ви можете просто сказатиx++;
- у призначенні немає потреби. Я б сказав, що це не слід визначати лише тому, що важко буде згадати, що повинно відбутися.