Pointer conversions to void* are implicit, but any other pointer conversion must be explicit. While the compiler allows an explicit conversion from any pointer-to-data type to any other pointer-to-data type, accessing an object through a wrongly typed pointer is erroneous and leads to undefined behavior. The only case that these are allowed are if the types are compatible or if the pointer with which your are looking at the object is a character type.

#include <stdio.h>

void func_voidp(void* voidp) {
    printf("%s Address of ptr is %p\\n", __func__, voidp);
}

/* Structures have same shape, but not same type */
struct struct_a {
    int a;
    int b;
} data_a;

struct struct_b {
    int a;
    int b;
} data_b;

void func_struct_b(struct struct_b* bp) {
    printf("%s Address of ptr is %p\\n", __func__, (void*) bp);
}

int main(void) {
/* Implicit ptr conversion allowed for void* */
func_voidp(&data_a);

/*
 * Explicit ptr conversion for other types
 *
 * Note that here although the have identical definitions,
 * the types are not compatible, and that the this call is
 * erroneous and leads to undefined behavior on execution.
 */
func_struct_b((struct struct_b*)&data_a);

/* My output shows: */
/* func_charp Address of ptr is 0x601030 */
/* func_voidp Address of ptr is 0x601030 */
/* func_struct_b Address of ptr is 0x601030 */

return 0;
}