Si se me permite un inciso, y por lo que sé, todos los punteros en C (repito: punteros) tienen el mismo tamaño: un tamaño capaz de guardar una dirección de memoria.
Otra cosa es el tipo del puntero: éste le dice al compilador el tamaño del dato al que se apunta para que cuándo se dereferencíe tome tantos bytes de la memoria a partir de la dirección del puntero para trabajar con él.
Es decir, un puntero en sí da igual que sea int, long, unsigned, o una función de muchos parámetros, es solo una dirección de memoria.
Por eso el void* puede convertirse en cualquier cosa, porqué únicamente guarda la información de la dirección, no del tamaño del dato y por eso el compilador necesita el cast, para saber cuántos bytes toma el dato que se guarda allí.
En los sistemas en modo real un puntero puede apuntar a cualquier sitio: a la memoria gráfica, a alguna parte del sistema operativo, a otros programas... y lo peor es que dejaba escribir allí. Por eso durante tanto tiempo los punteros eran una cosa muy temida, no académicamente, sino porqué podían causar auténticos desastres. También los virus tenían más acceso a la máquina.
Ahora con las protecciones propias del procesador y del sistema operativo un puntero mal dirigido lo único que puede conseguir es que el sistema cierre el programa.
Hasta donde yo se no hay ninguna garantía que un programa en C pueda usar un puntero void* para almacenar punteros a funciones (los punteros de funciones pueden usar otro tipo de direccionamiento). Había un apartado en la especificación en la que dejaba esto en claro. Hay otros estándares y extensiones que quizás puedan agregar esa limitación pero al menos el estándar en C no ofrece esa garantía.
Esto ya se sale fuera del tema.