Pasar a void ** en lugar de void * hace que el comstackdor se queje de los tipos, ¿por qué?

No entiendo por qué el comstackdor me advierte acerca de pasar un tipo de puntero incompatible en este código: (en este contexto, ¿cuál es la diferencia entre void * y void ** )? utilizando la versión gnu99 C)

 void someFunc(void ** foo) { printf("%s\n", *foo); } int main() { char * text = "some text"; someFunc(&text); return 0; } 

y en esto no

 void someFunc(void * foo) { printf("%s\n", foo); } int main() { char * text = "some text"; someFunc(text); return 0; } 

Gracias por adelantado

void * es un tipo que es convertible implícitamente hacia y desde cualquier tipo de puntero de objeto. void ** no es – así que mientras puede asignar un char * a un void * , no puede hacer lo mismo con char ** y void ** .

La razón es que son tipos incompatibles: char ** apunta a un char * , void ** apunta a un void * , por lo que sus tipos de base no coinciden.

Para corregir su código en el segundo ejemplo, puede hacer una de las siguientes acciones:

 // Solution A, preferred: void someFunc(char * foo) { printf("%s\n", foo); } int main() { char * text = "some text"; someFunc(text); return 0; } 

En A le está diciendo al comstackdor que el parámetro que se pasa es un puntero a un carácter. No he probado la solución B, debería funcionar, pero ¿por qué usar los vacíos si NO son absolutamente necesarios?

 // Solution B, should work but a purist might object: void someFunc(void * foo) { printf("%s\n", foo); } int main() { char * text = "some text"; someFunc( (void *) text); return 0; } 

En esta pregunta no hay ninguna razón obvia para usar un doble ptr, por lo que la Solución A para su segundo ejemplo es probablemente el camino a seguir.