TL;DR
Don't do any of this, it is dangerous and incorrect C for a number of reasons. My general advise to beginners is to never use the cast operator at all - there shouldn't be a lot of situations where you actually need to use it.
Generally, C allows wild and dangerous pointer conversions between object pointers that are not compatible, as long as there are no alignment concerns regarding the type pointed-at. (6.3.2.3/7)
However, should you first cast to a non-compatible type and then de-reference the pointer, all manner of undefined behavior might kick in. 6.7.6.1:
For two pointer types to be compatible, both shall be identically qualified and both shall be pointers to compatible types.
Also there are the whole "strict aliasing" concerns regarding "lvalue access" (6.5).
Specifically:
(unsigned int *)pp
the pointer conversion is probably ok given that pp
points at an aligned address.
*((unsigned int *)pp)
invokes undefined behavior since a lvalue of type void*
is accessed as an unsigned int
and they are not compatible types.
unsigned int *get_data_1 = <unsigned int lvalue>
is a constraint violation - invalid C. As per 6.5.16.1. C has never allowed an integer to get assigned to a pointer and vise versa, explicit casts are required.
(unsigned int **)pp
similarly the pointer conversion in itself is "probably ok". But again unsigned int**
is not compatible with void**
. Notably, the special generic rules regarding void*
conversions do not apply to void**
.
*((unsigned int **)pp)
accesses a void*
as a unsigned int*
. Again this is a strict aliasing violation, because although we may convert to/from void*
to any object pointer, they need not have the same internal presentation (though in practice it's very likely). They are not compatible types as per the quoted 6.7.6.1.
unsigned int *get_data_2 = <unsigned int* lvalue>
is ok.