Страницы

Поиск по вопросам

среда, 27 ноября 2019 г.

Почему ++i считается lvalue, а i++ rvalue?

#c++


Почему ++i считается lvalue, а i++ rvalue?
Я нашел ответ на данный вопрос на stackoverflow, но мой ужасный английский не позволяет
мне грамотно в этом разобраться. Ведь приоритет префиксного и постфиксного ++ всё равно
выше, чем & и по идее в любом случае будет сначала ++, а только потом & или я вообще
не так понимаю?
    


Ответы

Ответ 1



Потому что после выполнения выражений: i = 0; (1) x = ++i; (2) x = i++; В x будут следующие значения: (1) x = 1; i = 1; (2) x = 0; i = 1; Все эффекты связаны как раз с таким делением. То есть ++i означает увеличить i на один и взять его для выражения, а i++ означает взять значение i для выражения и после увеличить i на 1.

Ответ 2



Возможно, это очень неполный ответ по сравнению с развёрнутым первым по ссылке, но суть такая: Постфиксный оператор меняет значение и возвращает только временную копию этого значения, которая, как следствие, не может быть изменена. То есть эта копия идёт отдельно от самого значения i, и может быть использована в выражении, но присваивание к i++ не имеет смысла, т.к. результат i++ сохраняется в какой-то другой ячейке памяти, не в той, где лежит i. Результат ++i записывается в неё же, поэтому выражение ++i = ... имеет смысл (l-value).

Ответ 3



Век живи, век учись. Взял и попробовал обсуждаемые варианты. #include #include main () { int i = 0, x; x = (++i + ++i); printf ("i = 0; x = (++i + ++i): x=%d i=%d\n",x,i); i = 0; x = (i++ + i++); printf ("i = 0; x = (i++ + i++): x=%d i=%d\n",x,i); x = x++; printf ("x = x++: x=%d i=%d\n",x,i); #ifdef __cplusplus ++i = x; printf ("++i = x: x=%d i=%d\n",x,i); #endif } c:/Users/avp/src/cc/tst $ gcc t.c c:/Users/avp/src/cc/tst $ ./a i = 0; x = (++i + ++i): x=4 i=2 i = 0; x = (i++ + i++): x=0 i=2 x = x++: x=0 i=2 c:/Users/avp/src/cc/tst $ g++ t.c c:/Users/avp/src/cc/tst $ ./a i = 0; x = (++i + ++i): x=4 i=2 i = 0; x = (i++ + i++): x=0 i=2 x = x++: x=0 i=2 ++i = x: x=0 i=0 c:/Users/avp/src/cc/tst $ g++ --version g++.exe (GCC) 3.4.5 (mingw-vista special r3) Copyright (C) 2004 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. c:/Users/avp/src/cc/tst $ gcc --version gcc.exe (GCC) 3.4.5 (mingw-vista special r3) Copyright (C) 2004 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. c:/Users/avp/src/cc/tst $ c:/Users/avp/src/cc/tst $

Ответ 4



Оператор i++ никак не может возвращать lvalue по той простой причине, что нигде не существует подходящего lvalue для возвращения. Постфиксный оператор ++ обязан возвращать старое значение своего операнда. Однако когда побочные эффекты постфиксного ++ возымели свое действие, его операнд уже поменял свое значение на новое, а старое значения операнда больше нигде в памяти не хранится. Т.е. возвращаемое lvalue просто некуда "привязывать" в памяти. Единственными способами возвращения старого значения является либо запоминание этого старого значения во временном объекте, либо его вычисление "на лету" из нового значения. В обоих случаях старое значение не будет lvalue. Ситуация с префиксным оператором - обратная. Префиксный оператор должен возвращать новое значение своего операнда. Именно это новое значение операнд и будет содержать после реализации побочных эффектов префиксного ++. Поэтому операнд префиксного оператора как раз и является тем самым lvalue которое оператор сразу и вернет.

Ответ 5



Почему ++i считается lvalue, а i++ rvalue? Потому что эти операторы так объявлены в соответствии со стандартом: Прединкремент возвращает ссылку. Ссылке можно присвоить значение, а потому она lvalue («left side value», величина слева от знака равенства). Постинкремент возвращает значение. Значению ничего присвоить нельзя; его самого присваивают, а потому оно rvalue («right side value», величина справа от знака равенства).

Ответ 6



i++; /*называется постфиксной записью, в которой приоритет операции низкий*/ ++i; /*называется префиксной записью, в которой приоритет операции высокий*/ /*----------------------------------------------------------------------------------*/ int i = 5; int x = i++; /*здесь x == 5, а i == 6*/ int x = ++i; /*здесь x == 6, i == 6*/

Комментариев нет:

Отправить комментарий