Чому "++ i ++" недійсний, тоді як (++ i) ++ є дійсним?


14

Розглянемо наступний код:

int main() {
    int i = 2;
    int b = ++i++;
    return 3;
}

Він компілюється із наступним помилкою:

<source>: In function 'int main()':

<source>:3:16: error: lvalue required as increment operand

    3 |     int b = ++i++;

      |                ^~

Це звучить для мене справедливо. Приріст постфікса має більший пріоритет, ніж приріст префікса, тому код аналізується як int b = ++(i++);і iє оцінкою. Звідси помилка.

Давайте тепер розглянемо цей варіант із дужками для того, щоб змінити пріоритети за замовчуванням:

int main() {
    int i = 2;
    int b = (++i)++;
    return 3;
}

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

Питання: чому (++i)це lvalueколи iнемає?

Дякую!

ОНОВЛЕННЯ: наведене вище повідомлення про помилку було від gcc (x86-64 9.2). Ось точне відображення: помилка з gcc

Clang x86-64 9.0.0 має зовсім інше повідомлення: помилка з клангом

<source>:3:13: error: expression is not assignable

    int b = ++i++;

            ^ ~~~

З GCC у вас складається враження, що проблема полягає в операторі Postfix, і ви можете потім поглянути, чому ++iце нормально, а iні, звідси і моє запитання. З Кланг зрозуміліше, що проблема в операторі префікса.


Спочатку це було позначено
Анті

Справді шкода! Я припускав, що поведінка була однаковою в C ...
Bktero

Відповіді:


23

iі ++iє обома значеннями, але i++є оцінкою.

++(i++)не може бути дійсним, оскільки до ++нього застосовується префікс i++, який є оцінкою. Але (++i)++це добре, тому що ++iце значення.

Зауважте, що в С ситуація інша; i++і ++iобидві оцінки. (Це приклад того, чому люди повинні перестати вважати, що C і C ++ мають однакові правила. Люди вставляють ці припущення у свої запитання, які потім повинні бути спростовані.)


4

Ця декларація

int b = ++i++;

еквівалентно

int b = ++( i++ );

Оператор приросту postfix повертає значення операнду до приросту.

Зі стандарту C ++ 17 (8.2.6 збільшення та зменшення)

1 Значення виразу постфікса ++ - це значення його операнду ... Результат - первісне значення .

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

int b = (++i)++;

є дійсним. Можна, наприклад, написати

int b = (++++++++i)++;

Зі стандарту C ++ 17 (8.3.2 Приріст та зменшення)

1 Операнд префікса ++ модифікується додаванням 1. Операнд має бути зміненим значенням. Тип операнда має бути арифметичним типом, відмінним від cv bool або вказівника на повністю визначений тип об'єкта. Результат - оновлений операнд; це lvalue , і це бітове поле, якщо операнд - це бітове поле ....

Зверніть увагу, що в C обидва оператори повертають значення замість lvalue. Так у С ця декларація

int b = (++i)++;

недійсний.


3

тому код аналізується як int b = ++ (i ++); і я - рецензія.

Ні. iНе є оцінкою. iє значенням. i++являє собою оцінку (первісне значення, щоб бути конкретним).

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.