C11 6.5.3.1p1 :
- Операнд оператора увеличения или уменьшения префикса должен иметь атомарный, квалифицированный или неквалифицированный вещественный или указательный тип, идолжен быть изменяемым lvalue.
Это означает, что если у нас есть конструкция something ++
, то something
- должна быть действительной: целая или с плавающей запятой, но не можетможет быть комплексным числом
- или может быть указателем типа (но указатель void не подходит, поскольку для него не определена арифметика)
- также может быть
_Atomic
или volatile
- , но это должно быть lvalue , т.е. обозначать объект , который изменяется с шагом
- и этот lvalueдолжен быть изменяемым (например, он не может быть
const
квалифицированным)
Выражение
a + b
не является выражением lvalue, оно не обозначает объект.Это арифметическое выражение;и значение арифметического выражения не является lvalue.Хотя вы можете добавить 1 к этому значению, значение выражения не является объектом для изменения.
Однако, учитывая
int a, *b, c[5][6];
struct FOO { char *bar; } foo, *fooz;
double *funnyfunc(int x);
, все эти выражения являются изменяемыми скалярными lvalues:
a
*(b + 5)
c[1][4]
foo.bar
fooz->bar
funnyfunc(5)[42]
и вы можете применить к ним ++
.
Есть еще одна проблема с
c = (a + b) ++
значением постинкрементавыражение - это значение перед шагом , т. е. даже если бы это a + b
было изменяемым, c
не имело бы значения a + b + 1
, но в любом случае a + b
;и a + b
изменит свое сохраненное значение для последующих оценок.