I'm using VS Code and GCC compiler. Here's the code:
#include <stdio.h>
#include <stdlib.h>
int main()
{
void *ptr = malloc(100);
printf("%p\n", ptr);
printf("%p\n", (int *)ptr + 1);
printf("%p\n", (int *)ptr - 1);
void *ptr2 = ptr;
printf("%p\n", (int *)ptr2 + 1); // Works well
printf("%p\n", ++(int *)ptr2); // error: lvalue required as decrement operand
free(ptr);
return 0;
}
When I compile the code above, ++(int *)ptr2
gets the error: "lvalue required as decrement operand".
However, (int *)ptr2 + 1
does work.
Can anyone explain why this happens?
The result of a cast is not an lvalue. There's a footnote in the 6.5.4 Cast operators
section of ISO C11 which states that:
A cast does not yield an lvalue. Thus, a cast to a qualified type has the same effect as a cast to the unqualified version of the type.
Similarly, in 6.5.3.1 Prefix increment and decrement operators
, it states (my emphasis):
The operand of the prefix increment or decrement operator shall have atomic, qualified, or unqualified real or pointer type, and shall be a modifiable lvalue.
Hence what you're attempting to do is invalid.
The reason why (int *)ptr2 + 1
works is because ptr2
is an lvalue so it can be cast. The addition of 1
is done to the cast value and this is also valid.
The situation you are attempting is no different to something like ++(ptr+1)
, which is a different way of trying to increment a non-lvalue. It's because both your cast and the expression ptr+1
are ephemeral objects, required to exist only long enough to be used for the immediate operation (the addition or the cast, not the pre-increment).
Your problem goes away if you slightly re-engineer the way things are done (since void*
casts freely to and from most other pointers):
printf("%p\n", ptr2 = ((int*)ptr2) + 1);