Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

359
Vistas
void* como genérico en C, ¿es seguro?

prepárate para una pregunta un poco "retorcida"...

He implementado en el pasado una gran cantidad de estructura de datos (árbol, lista, tabla hash, gráfico también), usando la macro puedo implementar algún tipo de genérico. Sin embargo, estaba dudando si es posible implementar una estructura de datos genérica usando un puntero vacío, pero de alguna manera me gustaría poder usar una verificación de tipos ...

No sé si está claro lo que estoy tratando de decir... pero básicamente no creo que siempre sea seguro poner "void*" como genérico, al mismo tiempo no creo que siempre sea una buena idea usar la macro como una forma de hacer una estructura de datos genérica (ya que básicamente lo que hace un preprocesador con la macro es la sustitución de código), porque si buscas en la web puedes encontrar esos ejemplos.

Una buena idea podría ser, en mi opinión, pero probablemente no esté en lo cierto, usar la macro para hacer una interfaz estándar para los datos almacenados en una estructura de datos, entre las funciones de la interfaz, pondría el código para verificar el tipo correcto, dado evitar*. Inspirado en la técnica del ingeniero de software, esta podría ser una buena manera de proceder.

Seguramente es cierto que probablemente para cosas demasiado sofisticadas sería mejor cambiar de idioma (C++/Java) pero también es cierto que esto no siempre es posible.

Entonces, en resumen ... ¿cómo se maneja generalmente el problema de "genérico" en C? confío en su experiencia para una respuesta!

over 4 years ago · Santiago Trujillo
2 Respuestas
Responde la pregunta

0

Brevemente, no hay una forma conveniente de obtener funciones y estructuras de datos genéricas con seguridad de tipo en C.

No genérico:

 struct node { int value; struct node *next; };

Genérico, pero inseguro: un void* no tiene información de tipo:

 struct node { void *value; struct node *next; };

Seguro, pero feo:

 #define DECLARE_NODE_TYPE(type) \ struct node_##type { \ type value; \ struct node_##type *next; \ }; DECLARE_NODE_TYPE(int) node_int *x = ...

La misma idea, pero un poco menos fea:

 // declare_node_type.h struct node_##NODE_TYPE { NODE_TYPE value; struct node_##NODE_TYPE *next; }; #undef NODE_TYPE // elsewhere #define NODE_TYPE int #include "declare_node_type.h" node_int *x = ...

Genérico y seguro, pero C++, no C:

 template<typename T> struct node { T value; node<T> *next; }; node<int> *x = ...
over 4 years ago · Santiago Trujillo Denunciar

0

Puedes hacer cosas más seguras con void* ; volviendo al ejemplo vinculado de Jon Purdy:

 typedef struct { union { void* data; // generic data int idata; // int is not stored dynamically }; int type; // additional type information Node* next; // link } Node; #define NODE_TYPE_INT 0 Node* createNodeInt(Node* self, Node* next, int value) { self->idata = value; self->type = NODE_TYPE_INT; self->next = next; return self; } // in this case relying on user defined types... Node* createNodeGeneric(Node* self, Node* next, void* data, int type) { assert(type != NODE_TYPE_INT && ..); self->data = data; self->type = type; self->next = next; return self; }

Otro enfoque es utilizar el primer miembro común como tipo base:

 typedef struct { int type; } Node; #define TYPE_BINARY 0 typedef struct { Node base; Node* left; Node* right; int op; } BinaryOp; #define TYPE_LEAF_INT 1 typedef struct { Node base; int a; } LeafInt; #define TYPE_LEAF_FLOAT 2 typedef struct { Node base; float b; } LeafFloat; void op(BinaryOp* node) { switch(node->left.type) { case TYPE_BINARY: op((BinaryOp*)node->left); break; case TYPE_LEAF_INT: evalInt((LeafInt*)node->left); break; ... } } Node* foo() { LeafInt* left; LeafFloat* right; BinaryOp* op; // allocate ... // init createLeafInt(left, 42); createLeafFloat(right, 13.37); createBinaryOp(op, &left->base, &right->base); // and return return &op->base; } }
over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda