There is no way to do such a thing in C! Except by using a void*, which is not an efficient/safe way.
Perché credi che l'uso di un (void *) non sia un modo efficiente / sicuro?
Se vuoi nascondere i dettagli di implementazione in C, è una tecnica comune esporlo come typedef a (void*)
in un'intestazione e fornire funzioni per manipolarlo.
Ecco un'intestazione di exaple per un tipo dinamico contenente interi e stringhe:
/* Dynamic types in C */
#define DYNAMIC_INT 0
#define DYNAMIC_STRING 1
struct dynamic_phantom;
typedef struct dynamic_phantom* dynamic;
dynamic dynamic_of_int(int c);
dynamic dynamic_of_string(char *s);
int dynamic_classify(dynamic v);
int dynamic_get_int(dynamic v, int *c);
int dynanic_get_string(dynamic v, char **s);
void dynamic_free(dynamic v);
Spero che i nomi delle funzioni e dei loro prototipi siano sufficienti per ottenere ciò per cui sono. Ci sono molte opzioni per implementarlo. Lasciatemi delineare due scelte popolari:
SINDACATI
Nel tuo file di implementazione, implementa il dynamic
come union
come questo:
union dynamic_value {
int value_int;
char* value_string;
};
struct dynamic_cell {
int cell_type;
union dynamic_value cell_value;
};
typedef struct dynamic_cell *dynamic;
e implementare le funzioni che ho enumerato sopra è semplice. (Naturalmente, è possibile perfezionarlo in diversi modi, definendo procedure di controllo degli errori, aggiungendo bit di controllo se si desidera evitare la duplicazione dei contenuti delle stringhe e così via.)
PISCINE DI MEMORIA SPECIALIZZATE
Per ogni tipo dinamico disponibile, si assegna un pool di memoria, cioè una vasta gamma di tali valori. Un valore dinamico viene quindi implementato come puntatore a un valore in questi pool di memoria convertiti in void*
. Il tipo del valore viene quindi recuperato dall'intervallo del puntatore.
Un vantaggio di questa strategia rispetto al precedente è che tratta nativamente con valori di dimensioni diverse mentre l'approccio sindacale prende la dimensione più grande dei possibili tipi di valore. È tuttavia leggermente più complicato da implementare, soprattutto a causa della gestione della memoria: è necessario reimplementare in modo efficiente la logica di malloc
se si desidera gestire un numero significativo di valori.