Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

366
Visualizações
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 Respostas
Responde à pergunta

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 Relatório

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 Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda