Declarar tipo de variable genérica

Estoy tratando de declarar un tipo de variable genérica en C (no puedo usar C ++), y tengo en mente las siguientes opciones.

Opción 1

typedef struct { void *value; ElementType_e type; } Data_t; 

opcion 2

 typedef struct { ElementType_e type; union { int a; float b; char c; } my_union; } my_struct; 

donde ElementType_e es una enumeración que contiene todos los tipos posibles de variables (por ejemplo, int, char, unsigned int, etc.). Estoy un poco inclinado hacia la opción 1, porque no creo que el lanzamiento agregue tiempo de cómputo adicional, en comparación con el cambio, ¿verdad?

Me pregunto qué tipo es más útil? Sé que la opción 1 requerirá el lanzamiento cada vez que se use / acceda. ¿Hay algún problema posible que pueda ocurrir con la conversión (especialmente con la ejecución / comstackción del código en una plataforma diferente, por ejemplo, 32 bits y 16 bits micro)?

Mientras que option2 requiere un interruptor () para realizar cualquier operación (por ejemplo, adición, …).

El siguiente enlace explica que la Opción 2 es mejor (desde el punto de vista de la legibilidad), pero me preocupa principalmente el tamaño del código y el costo computacional. Tipo de datos generics en C [void *]

¿Hay algún problema posible que podría ocurrir con el casting

No, ya que no desea emitir, ya que no hay necesidad de emitir al asignar desde / a un puntero void (en C).

Me pregunto qué tipo es más útil?

Ambos lo hacen, por lo que depende, como

  • 1 es para los perezosos (ya que son pocos tipos de escritura y pocos nombres de variables para recordar).
  • 2 es para los cautelosos (ya que es de guardado de tipo, a diferencia de la opción 1, donde se pierde la información de tipo “real”, por lo que incluso puede asignar una dirección de variable de un tipo que no esté en ElementType_e ).

Refiriéndose a un comentario :

Con respecto al rendimiento, no espero una diferencia importante entre ambos enfoques (si se implementa sanamente), ya que ambas opciones necesitan declaraciones condicionales en la asignación a / desde (la excepción aquí son las variables de puntero, que para la opción 1 van sin declaraciones condicionales de asignación).

Recomiendo usar una unión. De hecho, yo mismo he usado uno en una situación similar:

 union sockaddr_u { struct sockaddr_storage ss; struct sockaddr_in sin; struct sockaddr_in6 sin6; }; 

Utilizo esta unión en código de socket donde podría estar trabajando con direcciones IPv4 o IPv6. En este caso particular, el campo “tipo” es en realidad el primer campo en cada una de las estructuras internas ( ss.ss_family , sin.sin_family y sin6.sin6_family ).

Creo que el problema no está bien planteado, ya que hay infinitos tipos de datos posibles que puede definir el progtwigdor. Considere, por ejemplo, la siguiente secuencia:

 typedef char S0_t; typedef struct { S0_t x; } S1_t; typedef struct { S1_t x; } S2_t; typedef struct { S2_t x; } S3_t; 

Es bastante claro que es posible seguir indefinidamente para definir tantos tipos nuevos como queramos.
Por lo tanto, no hay una manera directa de manejar estas posibilidades.

Por otro lado, como los punteros son de naturaleza más flexible, puede tomar la decisión de definir un tipo genérico relacionado solo con los tipos de punteros.
Por lo tanto, los tipos utilizados en su proyecto tendrán que ser sólo punteros.
De esta manera, probablemente algo muy simple como la siguiente definición podría funcionar:

  typedef void* generic_t;