Reputation: 7610
I tried to execute the following piece of code,
int val=10;
printf("%d",++val++);
As expected I got the following error message, "lvalue required as increment operand
". But when I made the following change the program was working fine.
int val=10;
int *ptr=&val;
printf("%d",++*ptr++);
The program gave an output of 11. The output value was not surprising.
But the whole construct ++*ptr++
being an lvalue
and not an rvalue
was confusing.
I printed the contents of ptr
before and after as follows,
printf("%u\n",ptr);
printf("%d",++*ptr++);
printf("\n%d\n",ptr);
2293532 and 2293536 were the addresses printed on screen. So clearly ptr
has incremented and pointer addition is involved.
The output makes sense except for the fact that *ptr
retrieves the content of the variable whose address is stored in ptr
which is 10 and ++*ptr
increments it to 11. This definitely is an rvalue
. But the post increment (++
) has been bound to ptr
I believe. Why so? What rules govern such bindings in C?
Upvotes: 2
Views: 135
Reputation: 18825
Your observation is correct, i.e. prefix ++
is applied to the value the pointer points to (int), while the postfix ++
is applied to the pointer itself.
This is due to fact that postfix ++
operator has higher priority than *
and therefore takes precedence. So first ptr
is incremented and its original value is returned, then this pointer is dereferenced and the int
value it points to is incremented and returned by the expression. The prefix ++
is applied after *
because of its order and dependency in the code, and they have equal priority anyway.
PS: The correct formatter to print pointer is "%p".
Upvotes: 6
Reputation: 213693
printf("%d",++val++);
Postfix ++ has higher operator precedence than prefix ++, therefore val++
is evaluated first. The result of the operation is a rvalue - it can't be modified. But the prefix ++ operator expects the operand to be an lvalue (modifiable), so the expression isn't valid.
printf("%d",++*ptr++);
Here the operator precedence is such that postfix ++ still has highest precedence. ptr++
will get evaluated first, which means that pointer arithmetic is applied to increase the address of ptr
by one element. The increment happens after ptr
has been evaluated.
Prefix ++ and unary * have the same precedence, but operator associativity for this group of operators is right-to-left, meaning that *, being most to the right, gets evaluated first. Unlike the ++ operators, the unary * doesn't require a lvalue operand. It is sufficient that it gets a pointer type operand, which it does in this case.
As a special case, the unary * operator, when applied to a pointer-to-object, gives a result which is a lvalue. Therfore the prefix ++ now work, where it failed in the previous expression. It will however not increment the pointer, but the pointed-at contents: integer addition by 1.
Please note that you should never mix the ++ operators with other operators, since a ++ operation involves a side effect. Doing so is bad practice and might invoke undefined behavior bugs. See this for details.
Upvotes: 2