В этом объявлении
int *p = &++x;
используются два унарных оператора: преинкремент ++ и получение адреса. Унарные операторы выполняются справа налево. Поэтому сначала переменная x
увеличивается, и ее адрес присваивается указателю p. Результатом оператора предварительного увеличения является lvalue
увеличенного объекта.
Так, например, такое выражение, как это
++++x;
, является правильным.
В этом объявлении
int *p = &x++;
используется оператор postfix post-increment ++ и унарный оператор взятия адреса. Операторы Postfix имеют более высокий приоритет по сравнению с унарными операторами. Поэтому сначала выполняется постинкремент. Его результатом является временный объект, который имеет значение переменной x перед увеличением. Затем выполняется оператор получения адреса.
Однако вы не можете взять адрес временного объекта. Поэтому для этого объявления компилятор выдаст ошибку.
В противоположность оператору предварительного приращения такое выражение, как это
x++++;
, недопустимо.
Из C ++ 17 Стандарт (5.3.2 Увеличение и уменьшение)
1 Операнд префикса ++ изменяется путем добавления 1 или устанавливается в значение true, если это bool (это использование не рекомендуется). Операндом должно быть изменяемое значение l. Тип операнда должен быть арифметическим c типом или указателем на полностью определенный тип объекта. Результатом является обновленный операнд; это lvalue , и это битовое поле, если операнд является битовым полем ....
И (5.2.6 Увеличение и уменьшение)
1 Значением выражения postfix ++ является значение его операнда. [Примечание: полученное значение является копией исходного значения - примечание конца] ...
В C обе операции дают значение. Так что в C вы тоже не можете писать
++++x;