Your question is tagged with C ++, but still to start a few words about C:
In C, a pointer of type int * can formally have an object representation that is different from the object representation of a pointer of type void * . In the C language, only all pointers to struct types (among themselves), all pointers to union types (among themselves), and also pointers void * and [signed/unsigned] char * (among themselves) have the same object representations (plus, of course their cv-qualified variations). No more matches for object representations of pointers are guaranteed.
This means that an attempt to write a void * value to an int * type pointer through memory re-interpretation (type punning) is not formally correct from the point of view of the language. The language unequivocally says that accessing an object of type int * as to an lvalue of type void * any way other than through a union leads to undefined behavior (see 6.5 / 7). This is the so-called rule (or axiom) strict aliasing.
Therefore, there is no formally portable way to make scanf("%p" directly into an int * type pointer. Even if the object representations of these types are the same, and even if your attempts to "strangle" the compiler warnings were successful, this still does not mean that your program will work correctly. The compiler, based on the above rules strict alising, has every right to believe that your scanf("%p" does not modify the pointer p (because he can not legally modify it), that is to ignore the relationship between the information you ovom scanf and the value of p .
Young Pioneer practitioners from the C sect is such a portable assembler for quite some time managed to ignore strict aliasing considerations and used type punning in their code to the right and left, regarding it as something of a secret knowledge that distinguishes them from the theorists. This continued until GCC and other compilers began actively using the most valuable information based on the axioms of strict aliasing in their optimizations. The howl that rose as a result of the swamps of the “practitioners” of this kind did not finally subside to this day. That's it from vlyapyvaniya in this swamp and trying to protect you compiler with your warnings.
If you want to read the value for your p through scanf , then perhaps the only civilized way is
int *p; void *v; scanf("%p", &v); p = v; // с явным кастом для C++
Or, if you really want to do type punning, then through union
union { int *p; void *v } u; scanf("%p", &u.v); p = up;
Type punning through the union was legalized in C99 (TC3, it seems). Of course, with the proviso that all responsibility for the correctness of the resulting object representation falls on you.
The above is directly related to C ++, except that type punning through union in C ++ is not legalized.
scanffunction is unsafe ... Yes, and here without any warnings ... - Harrysize. Want a pointer to int? Or double? How can the compiler distinguish between them? Therefore, we need an explicit type conversion - DNS