25

Assuming the definition:

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

Why is *p a valid lvalue here:

*p+=10; 

Shouldn't *p evaluate to the value of the int stored at &i, ie. 10, and hence generate a "Not an lvalue" error?

laalto
  • 150,114
  • 66
  • 286
  • 303
  • 1
    I don't know why you got downvoted. I think this is a fine question – SiegeX Jan 24 '11 at 19:51
  • 2
    I always thought of `*p` as a synonym for `i`, and never ran into any confusion. – Kevin Jan 24 '11 at 20:24
  • 4
    `*p` "evaluates to the value of the int stored at `&i`" when used as an rvalue. But as an lvalue, it's the same as the lvalue `i`. – aschepler Jan 24 '11 at 20:34
  • 2
    `*p` always means "the contents of the location pointed to by `p`". The difference between the interpretation of `*p` as an lvalue vs. an rvalue is that when `*p` appears as an lvalue it's understood that the intent is to *store into* the location pointed to by `p`, while when `*p` is used as an rvalue it's understood that the intent is to *retrieve the contents* of the memory location pointed to by `p`. – Bob Jarvis - Слава Україні Dec 25 '17 at 19:18
  • @Kevin - my internal mental reading of `*p` is "the object of the pointer p". A bit wordy, perhaps, but mentally this translates `*p += 10` into "the object of the pointer p is incremented by 10". – Bob Jarvis - Слава Україні Dec 25 '17 at 19:22
  • On a philosophical note, if `*p` always was an r-value, what would be the point of pointers? They'd be effectively read-only... – Jens Dec 25 '17 at 20:31

5 Answers5

15

An lvalue is an expression that refers to a region of storage that can be manipulated.

*p is such an expression that refers to a region of storage. This is different than say 10+=10; because 10 doesn't refer to a region of storage like a variable would.

ikegami
  • 367,544
  • 15
  • 269
  • 518
SiegeX
  • 135,741
  • 24
  • 144
  • 154
3

C11 6.5.3.2p4:

Semantics

...

  1. The unary * operator denotes indirection. If the operand points to a function, the result is a function designator; if it points to an object, the result is an lvalue designating the object. If the operand has type ''pointer to type'', the result has type ''type''. If an invalid value has been assigned to the pointer, the behavior of the unary * operator is undefined

I.e. with

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

the result of *p is an lvalue that designates the object i.

Therefore *p += 10 works, as it is an lvalue.

Now, if an lvalue were used in a context where the object itself is needed, it would be converted to the value stored in the designated object. This is called the lvalue conversion, and the resulting value of course isn't an lvalue anymore (C11 6.3.2.1p2).

Community
  • 1
  • 1
2

Shouldn't *p evaluate to the value of the int stored at &i, ie. 10, and hence generate a "Not an lvalue" error?

In simple words,

* means "value at address".

*p means "value at address given by the value of p".

*p = 10; means "set 10 as the value at address given by the value of p".

lvalue is an expression that refers to an object stored somewhere in the memory. *p is also an expression that refers to an object stored at location p.

Maxim
  • 1,783
  • 2
  • 14
  • 24
2

I believe you are confused with the definition of p. p is, in fact, a variable of type pointer to int, and its value is initialized to the address of i.

Nonetheless, *p is a valid lvalue as well - a valid expression to a storage location.

Michael Foukarakis
  • 39,737
  • 6
  • 87
  • 123
2

In very simple words, pointers point to an object (in a general, non OOP sense), not to the contents of that object. So yes, a dereferenced pointer is a valid lvalue.

In very low level terms. A pointer is nothing but a memory address, a dereferenced pointer is the memory at that address.

wich
  • 16,709
  • 6
  • 47
  • 72