unsigned int num = 101;
void * p = #
void ** pp = &p;
unsigned int *get_data_1 = NULL;
unsigned int *get_data_2 = NULL;
get_data_1 = *((unsigned int *)pp);
get_data_2 = *((unsigned int **)pp);
Here get_data_1 and get_data_2 what will be the difference?
I have type casted with (unsigned int *) and (unsigned int **).
CodePudding user response:
Both operations invoke Undefined Behavior. The value of type void*
pointed by pp
is accessed via a l-value expression of incompatible type unsigned int
or unsigned int*
respectively. This violates strict aliasing rule.
As both operations are UB thus there is no defined difference between those two operations.
The correct accessing should be by dereferencing pp
first to obtain value of type void*
and use implicit casting from void*
to unsigned int*
. Finally dereference correctly typed pointer:
unsigned int *get_data_3 = *pp;
return *get_data_3;
CodePudding user response:
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 thatpp
points at an aligned address.*((unsigned int *)pp)
invokes undefined behavior since a lvalue of typevoid*
is accessed as anunsigned 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 againunsigned int**
is not compatible withvoid**
. Notably, the special generic rules regardingvoid*
conversions do not apply tovoid**
.*((unsigned int **)pp)
accesses avoid*
as aunsigned int*
. Again this is a strict aliasing violation, because although we may convert to/fromvoid*
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.