Why ++(*p) is not giving l-value required error?

213 Views Asked by At
#include <stdio.h>
int main()
{
    int arr[] = {1, 2, 3, 4, 5};
    int *p = arr;
    ++*p;
    p += 2;
    printf("%d", *p);
    return 0;
}

Why is this code not giving any compile time error,My doubt is ++*p is evaluated as ++(*p) and *p will be constant value 1 ,when we do ++(1) which is not a l-value,why is compiler not giving an error?

5

There are 5 best solutions below

0
On

Why ++(*p) is not giving l-value required error?

Dereference operator on a pointer yields a lvalue. Therefore, *p is a lvalue and using pre-increment operator on it is valid.

0
On

*p will be constant value [...]

No, it is the same as arr[0].

So

++(*p);

is the same as

++(p[0]);

is the same as

++(arr[0]);

which is a perfectly valid statement.

0
On

*p will be constant value

No, it won't. *p is a[0] when you do int *p = arr;. a[0] is not a constant value, and since they are the same, *p is not a constant value either.

As a result, this:

++(*p);

is equivalent to:

++(a[0]);

which increments the element at the first position of the array, as you can see clearly.

But looking back at ++(*p), one can see that:

  • *p dereferences the pointer, resulting in an l-value.
  • Then we have (*p), the l-value in parentheses.
  • ++(*p) applies the pre-increment operator to an l-value, which is value, thus no compiler error should be generated.
5
On

Just note both the statements used by you :

++*p; // increments the value pointed by *p at that time `a[0]` by 1
p += 2; // increments the address p is storing by 2

And the reason there is no l-value required error is because in your statement :

++*p; // *p is not a constant, it is same as a[0]
1
On

Object pointer dereferencing does not itself produce the value to which the pointer points. Instead it produces an lvalue that refers to that value. In the words of the standard:

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".

(C2011, 6.5.3.2/4; emphasis added)

Unary * is thus among a class of operators that can be considered to operate on the identity of an object, as opposed to on its value. The & operator and and some uses of the sizeof operator can also be considered to be in this category.