Estoy escribiendo una función donde me gustaría aceptar 2 type
s de parámetros.
- A
string
(char *) - A
structure
donde habrá n número de elementos.
Y para lograr esto, estoy pensando en usar un tipo simple void *
como parámetro. Pero no sé cómo verificar si el parámetro es de un tipo u otro, de forma segura.
void*
apuntan.func_str
efunc_struct
y recibir cheques de tipo en tiempo de compilación._Generic
macro. También podría crear tipos autoidentificables, por ejemplo, con uniones etiquetadas , lo que significaría que no puede pasar unachar *
cadena sin procesar . Todo eso es probablemente más problemas de lo que vale.Respuestas:
La traducción de
void*
es"Estimado compilador, este es un puntero, y no hay información adicional para usted sobre esto".
Por lo general, el compilador sabe mejor que usted (el programador), debido a la información que obtuvo antes y que aún recuerda y que quizás haya olvidado.
Pero en este caso especial, usted sabe mejor o necesita saber mejor. En todos los casos,
void*
la información está disponible de otra manera, pero solo para el programador, que "sabe". El programador debe proporcionar la información al compilador, o mejor al programa en ejecución, porque la única ventaja quevoid*
tiene es que la información puede cambiar durante el tiempo de ejecución.Por lo general, esto se realiza al proporcionar la información a través de parámetros adicionales a las funciones, a veces a través del contexto, es decir, el programa "sabe" (por ejemplo, para cada tipo posible hay una función separada, la función que se llame implica el tipo).
Entonces, al final
void*
no contiene la información de tipo.Muchos programadores malinterpretan esto como "No necesito saber la información de tipo".
Pero lo contrario es cierto, el uso de
void*
aumenta la responsabilidad del programador para realizar un seguimiento de la información de tipo y proporcionarla de manera adecuada al programa / compilador.fuente
void*
función, convierte al tipo incorrecto, luego des-referencia los datos ... entonces se invoca todo tipo de comportamiento indefinido.void*
están en desuso para la programación genérica, no hay muchas situaciones en las que deba usarlas hoy en día. Son peligrosos porque conducen a una seguridad de tipo inexistente. Y como notó, también pierde la información de tipo, lo que significa que tendría que arrastrar algo engorrosoenum
junto con elvoid*
.En su lugar, debe usar C11,
_Generic
que puede verificar los tipos en tiempo de compilación y agregar seguridad de tipo. Ejemplo:Recuerde proporcionar
const
versiones calificadas ( ) de todos los tipos que desea admitir.Si desea mejores errores de compilación cuando la persona que llama pasa el tipo incorrecto, puede agregar una afirmación estática:
Si intenta algo así
int x; func(x);
, recibirá el mensaje del compilador"x: incorrect type"
.fuente