int x, y;
int main() {
x++ + ++y;
x+++ ++y;
x++ +++y;
x +++++ y;
}
Почему эта программа не выдаёт ошибок для 1 и 2 строки, но выдаёт их для 3 и 4?
Первая строка будет разбита на токены следующим образом:
x
, ++
, +
, ++
, y
, ;
.
Что в итоге даст expression statement
с валидным выражением (постфиксный инкремент x
, префиксный инкремент y
и бинарный оператор сложения).
Вторая строка разобьётся на токены аналогично первой строке, потому что preprocessing tokens
† вычисляются по принципу maximal munch, а максимальным валидным предварительным токеном будет ++
, а не +++
.
lex.pptoken#3.3:
If the input stream has been parsed into preprocessing tokens up to a given character:
Третья строка будет разбита на токены следующим образом:
x
, ++
, ++
, +
, y
, ;
.
Отличие от первой и второй строки потому, что после 3 базового символа +
нет white space
, который в предыдущих случаях разделял предварительные токены +
и ++
.
В итоге получаем expression statement
с невалидным выражением, т.к. к результату постфиксного инкремента применяется постфиксный инкремент.
expr.post.incr#1:
... The operand shall be a modifiable lvalue. ... The result is a prvalue. ...
Четвёртая строка разобьётся на токены аналогично третьей строке, потому что:
white space
после x
и перед y
не влияет на вычисление предварительных токенов;white space
после 2 базового символа +
не влияет на вычисление предварительных токенов аналогично 1 и 2 строкам.† Подробнее о фазах трансляции можно почитать тут. Тогда станет понятно, зачем разделять предварительные и обычные токены.
error: lvalue required as increment operand
x++ +++y;
^
error: lvalue required as increment operand
x +++++ y;
^
Перевод : прибавление единицы возможно только к адресуемой переменной, а не временному числу.
Примеры НЕ lvalue значений и ошибок :
++ ( 2 + 2 ) ;
int f ( int ) ;
++ f ( 1 ) ;
Первые примеры разбираются компилятором с помощью приоритета операций. Инкремент ++ имеет очень высокий приоритет и вычисляются так:
x++ + ++y; => (x++) + (++y);
x+++ ++y; => (x++)+ (++y);
Ошибочные так :
x++ +++y; => (x++) (++(+y));
x +++++ y; => (x ++)(++(+ y));
где +y
или -y
это уже не lvalue значение.
Возвращаемое значение у постфиксного и у префиксного оператора тоже разное. ++y
возвращает lvalue, а y++
- rvalue. Поэтому:
++(++y) - OK
++(y++) - error
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Пишу веб сокет сервер на языке javaЕсть ксласс с обработчиком событий: открытие, закрытие соединения, ошибки, и сообщения
Столкнулся с проблемой повторной инициализации библиотекипри первом вызове все отрабатывает отлично, но после истечения некоторого времени...
Пишу приложение на java с использованием SpringНужно передать значение ключа из файла app