The type of the pointer p
does not change with either of the two: p = (char *)((int*)(p));
p = (int*)(p+1);
.
It still remains a pointer to a char
.
The cast only works to alter values (or types) in expressions. It applies to copies of values extracted from variables but does not modify those variables. Once the expression is over, the cast is gone with the value copy it was associated with.
Example:
signed char c = -1;
int i;
i = (unsigned char)c;
Here the value of c
, -1, is converted/cast to the type unsigned char
. If chars are 8-bit, the result of (unsigned char)-1
is 255 and this value is of type unsigned char
, which then gets converted to int
and assigned to i
.
c
does not change anyhow in the above process.
Example 2:
unsigned u = 0x55AA;
unsigned* pu = &u;
unsigned char* pc = (unsigned char*)pu;
Here pu
is converted/cast to type pointer to unsigned char
. That conversion does not modify the variable pu
, it only changes a copy of its value. And here it just changes the type of the copy, not the actual address, contained in the pointer variable. And then this copy of the address is assigned to pc
. The cast is needed to avoid compiler warnings/errors, because the compiler has all the rights to "wonder" what is going on here and if there might be a programming mistake.
Now both pu
and pc
point to the same location, the beginning of the variable u
. But they have different types, one points to an unsigned char
and the other, to an unsigned int
.
And so if you dereference pu
and pc
, you'll get different values and those will be of different types as well.
Likewise, if you do pointer arithmetic on the two pointers, for example, adding 1 to each, they will advance to point to different locations in memory. pu+1
will point to the location right after the end of u
and pc+1
will point to the 2nd unsigned char
from the beginning of u
.
Are you starting to see it?