Принимая определение:
int i = 10;
int *p = &i;
Почему *p является допустимым lvalue здесь:
*p+=10;
Не должен ли *p оценивать значение int, хранящегося в &i, т.е. 10 и, следовательно, генерировать ошибку «Не lvalue»?
Принимая определение:
int i = 10;
int *p = &i;
Почему *p является допустимым lvalue здесь:
*p+=10;
Не должен ли *p оценивать значение int, хранящегося в &i, т.е. 10 и, следовательно, генерировать ошибку «Не lvalue»?
lvalue — это выражение, указывающее на область хранения, которой можно управлять.
*p
— это такое выражение, которое относится к области хранения. Это отличается от 10+=10;
, потому что 10
не относится к области хранения, как переменная.
Я полагаю, вы запутались с определением p
. p
на самом деле является переменной типа указатель на int, и ее значение инициализируется по адресу i
.
Тем не менее, *p
также является допустимым lvalue — допустимым выражением для места хранения.
Проще говоря, указатели указывают на объект (в общем смысле, не относящийся к ООП), а не на содержимое этого объекта. Так что да, разыменованный указатель является допустимым lvalue.
В терминах очень низкого уровня. Указатель — это не что иное, как адрес памяти, разыменованный указатель — это память по этому адресу.
Не следует ли
*p
оценивать значение int, хранящегося в&i
, т.е. 10 и, следовательно, генерировать ошибку «Не lvalue»?
Простыми словами,
*
означает "значение по адресу".
*p
означает "значение по адресу, заданному значением p
".
*p = 10;
означает "установить 10 как значение по адресу, заданному значением p
".
lvalue — это выражение, которое ссылается на объект, хранящийся где-то в памяти. *p
также является выражением, которое относится к объекту, хранящемуся в местоположении p
.
Семантика
...
- Унарный оператор
*
обозначает косвенность. Если операнд указывает на функцию, результатом является указатель функции; если он указывает на объект, результатом будет lvalue, обозначающее объект. Если операнд имеет тип «указатель на тип», результат имеет тип «тип». Если указателю присвоено недопустимое значение, поведение унарного оператора*
не определено.
т.е. с
int i = 10;
int *p = &i;
результатом *p
является lvalue, обозначающее объект i
.
Поэтому *p += 10
работает, так как это lvalue.
Теперь, если бы lvalue использовалось в контексте, где необходим сам объект, оно было бы преобразовано в значение, хранящееся в указанном объекте. Это называется преобразованием lvalue, и результирующее значение, конечно же, больше не является lvalue (C11 6.3.2.1p2).
*p
синонимомi
и никогда не путался. - person Kevin   schedule 24.01.2011*p
оценивается как значение int, хранящегося в&i
, при использовании в качестве rvalue. Но как lvalue это то же самое, что и lvaluei
. - person aschepler   schedule 24.01.2011*p
всегда означает содержимое местоположения, на которое указываетp
. Разница между интерпретацией*p
как lvalue и rvalue заключается в том, что когда*p
появляется как lvalue, подразумевается, что цель состоит в том, чтобы сохранить место, на которое указываетp
, а когда*p
используется в качестве rvalue понимается, что цель состоит в том, чтобы получить содержимое области памяти, на которую указываетp
. - person Bob Jarvis - Reinstate Monica   schedule 25.12.2017*p
является объектом указателя p. Возможно, немного многословно, но мысленно это переводит*p += 10
в объект указателя p, который увеличивается на 10. - person Bob Jarvis - Reinstate Monica   schedule 25.12.2017*p
всегда было r-значением, в чем был бы смысл указателей? Они будут эффективно доступны только для чтения... - person Jens   schedule 25.12.2017