According to the C standard, you can convert any pointer to void * and convert it back, it will have the same effect.
To quote C11 , chapter §6.3.2.3
[...] A pointer to any type of object can be converted to a pointer to void and vice versa; The result should compare with the original pointer.
That's why when you overlay a void pointer on an int * , de-link and print the result, it prints correctly.
However, the standard does not guarantee that you can dereference this pointer to another data type. Essentially, it invokes undefined behavior.
So, dereferencing pf or pd to get a float or double is undefined behavior , since you read the memory allocated for an int like float or double . There's a clear case of mismtach that leads to UB.
To clarify, int and float (and double ) have different internal representations, so trying to overlay a pointer to another type, and then trying to dereference to get a value of another type will not work.
Associated, C11 , chapter §6.5.3.3
[...] If the operand is of type '' a pointer to a type, the result is of type ''. If an invalid value has been assigned to the pointer, the behavior of the unary * operator is undefined.
and for the invalid part of the value (my selection)
Among the invalid values for dereferencing a pointer by the unary operator * is a null pointer, an address that is incorrectly selected for the type of object that it points to , and the address of the object after the end of its service life.