Является ли разыменованный указатель действительным значением lvalue? - PullRequest
19 голосов
/ 23 января 2011

Принимая определение:

int i  = 10;
int *p = &i;

Почему * p является действительным значением lvalue здесь:

*p+=10; 

Не должен * p вычислять значение int, хранящееся в & i, т.е. 10, и, следовательно, сгенерировать ошибку "Not lvalue"?

Ответы [ 5 ]

13 голосов
/ 24 января 2011

lvalue - это выражение, которое относится к региону хранилища, которым можно манипулировать.

*p - это такое выражение, которое относится к области хранения. Это отличается от, скажем, 10+=10;, потому что 10 не относится к области хранения, как переменная.

2 голосов
/ 09 октября 2013

Не должен *p вычислять значение int, хранящееся в &i, т.е. 10 и, следовательно, сгенерировать ошибку "Not lvalue"?

Проще говоря,

* означает «значение по адресу».

*p означает «значение по адресу, заданное значением p».

*p = 10; означает «установить 10 в качестве значения по адресу, заданному значением p».

lvalue - это выражение, которое относится к объекту, хранящемуся где-то в памяти. *p также является выражением, которое относится к объекту, хранящемуся в местоположении p.

2 голосов
/ 25 января 2011

Проще говоря, указатели указывают на объект (в общем смысле, не в ООП), а не на содержимое этого объекта. Так что да, разыменованный указатель является допустимым lvalue.

В условиях очень низкого уровня. Указатель - это не что иное, как адрес памяти, разыменованный указатель - это память по этому адресу.

2 голосов
/ 24 января 2011

Полагаю, вы запутались в определении p.p фактически является переменной типа , указывающей на int , и ее значение инициализируется по адресу i.

Тем не менее, *p является допустимым значением lvalueа также - допустимое выражение для места хранения.

1 голос
/ 25 декабря 2017

C11 6.5.3.2p4 :

Семантика

...

Унарный оператор * обозначает косвенность.Если операнд указывает на функцию, результатом является обозначение функции; если он указывает на объект , результатом является lvalue, обозначающее объект .Если операнд имеет тип «указатель на тип», результат имеет тип «тип».Если указателю присвоено недопустимое значение, поведение унарного оператора * не определено

То есть с

int i  = 10;
int *p = &i;

результатом *p является lvalue, обозначающим объект i.

Поэтому *p += 10 работает так же, как и lvalue.

Теперь, если lvalue использовалось в контексте, где сам объектнеобходимо, это будет преобразовано в значение, хранящееся в назначенном объекте .Это называется преобразованием lvalue , и полученное значение, конечно, больше не является lvalue ( C11 6.3.2.1p2 ).

...