Deepu
Deepu

Reputation: 7610

lvalue returned with pointer in C

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

Answers (2)

Zbynek Vyskovsky - kvr000
Zbynek Vyskovsky - kvr000

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

Lundin
Lundin

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

Related Questions