Supponiamo che una funzione assuma come argomento un puntatore vuoto, ad esempio: int func(void *p);
Come possiamo determinare o indovinare il tipo di cosa sta puntando p?C: estrapola il tipo dal puntatore vuoto
risposta
In generale, non è possibile. In alcuni casi, se c'è una garanzia su cosa punta p, potresti essere in grado di vedere i contenuti a questo indirizzo e dopo di esso per scoprirlo. In generale, la tua funzione dovrebbe sapere cosa viene passato, a meno che non lo passi semplicemente.
Gli argomenti di dati e funzioni in C sono solo un insieme di bit raggruppati insieme. A meno che non usi alcuni di quei bit per dirti quali sono i bit, non esiste un modo coerente per identificarli.
Risposta breve: non è possibile.
In C non ci sono informazioni di tempo di esecuzione a meno che non fornirlo, ma guarda al printf(3)
famiglia e vedere come sia facile spararsi in un piede con il formato spec non corrispondenti e tipo di argomento reale.
Il sistema di tipo è tuo amico. Usalo.
Certo che puoi, ed è anche facile. È C, fai quello che vuoi, come lo vuoi.
Creare un sistema di tipi. Metti tutto in una struttura, fai il primo o il secondo numero magico per determinare cosa contiene la struttura oltre il numero magico.
Crea alcune funzioni per creare/ottenere/impostare/distruggere le "variabili digitate".
Crea alcune altre funzioni per aggiungere e registrare nuovi tipi in fase di esecuzione.
Creare alcune definizioni per semplificare la lettura e la tipizzazione delle strutture.
Prima che tu lo sappia, avrai un bel sistema di tipo proprietario che puoi usare per i tuoi progetti, e farà sempre ESATTAMENTE quello che vuoi e di cui hai bisogno perché l'hai fatto.
Potresti impazzire e trasformarlo in un sistema completamente orientato agli oggetti. O risparmia te stesso il lavoro, e usa il lavoro di tutte le altre persone che sono già impazzite - http://en.wikipedia.org/wiki/GObject
Quindi, come funziona quando la funzione che scrivi viene chiamata dal codice che non controlli? – WhirlWind
Se la funzione viene chiamata dal codice che non controlli, allora stai creando l'API/Libreria, quindi devi documentare l'interfaccia e le funzioni per creare/ottenere/impostare/distruggere le variabili digitate. Se per qualche motivo il callee è quello in controllo, e non vogliono/rifiutano di usare il tuo sistema 'tipizzato' personalizzato, allora sei sfortunato. Devi permettere loro di decidere come passare le informazioni digitate e il codice a quello. – Antebellum
Mi sono confrontato con un problema simile e mi sono ritrovato a dover scrivere un set di istruzioni per un progetto di linguaggio di programmazione. Mi sono imbattuto in questo problema perché avevo una serie di puntatori alle funzioni in modo che le funzioni potessero essere enumerate ed eseguite in un ciclo for (per cose come la guida in linea e la sintassi, ecc.). Per esempio:
struct List_Str *(*InstructionSet[])(struct List_Str *ContextPrefix,struct List_Str *ContextSuffix)=
{
AAVF,Add,AddEmotions,AddEmoDebug,AddScope,...
};
Ora si potrebbe facilmente fare la stessa cosa con char * al posto di struct List_Str * tipi, poi convertire tutti i dati in formato stringa utilizzando snprintf e atoi e atof e altre funzioni di conversione. Se fate una:
man isalpha
Questo mostra un sacco di funzioni in ctype.h che potrebbe darvi idee su come determinare quale tipo di dati si svolge all'interno delle stringhe.
La piegatura di tutti i tipi in formato "filante" consente un'enorme flessibilità e regolarità, ma la conversione automatica dei dati dalle stringhe a numeri interi, float, ecc. È ardua, ma proficua una volta che le routine sono ordinate.
Se si desidera conservare dati binari, non è possibile utilizzare le stringhe, poiché 0 caratteri possono essere contenuti nei dati binari e questo confonde le funzioni strlen. Inoltre, non si ha idea della lunghezza di ciò che è stato malloc'd una volta che lascia l'ambito, quindi memorizzare la lunghezza dei dati sottoposti a dereferenziazione prima che i dati siano raccomandati nei primi pochi byte di char *.
Un'ultima cosa, non raccomanderei di memorizzare i dati nel vuoto *, è troppo vago. Ti consiglio di usare char * in quanto è un po 'più specifico, può contenere tutto ciò che è vuoto * e il compilatore ti avviserà in anticipo se qualcosa sembra sospetto.
Se si utilizza 'char *' come un puntatore generico di dati, è troppo facile che IMHO rilasci accidentalmente il puntatore senza prima convertirlo nel tipo corretto. –
Votare questo ... lo sai perché ti sei assicurato dei tipi nel resto del tuo programma. Se questo sembra fragile, è perché è fragile. Benvenuto in C. Usa un sistema meno fragile dove puoi. –
Ricordo un po 'di codice Motif (di tutte le cose) un po' indietro dove si otterrebbe un puntatore, e si guarderebbero i primi byte dopo il puntatore per determinare quale fosse il tipo, e quindi si gestirà quel tipo in modo appropriato. Che casino. – WhirlWind
Non lo farò in pratica. Ero solo curioso di come questo possa essere fatto. Inoltre, un'estensione GNU C fornisce l'operatore typeof() che (penso) sarà in grado di determinare il tipo di ciò che è dereferenziato (cioè typeof (* p)), ma non l'ho ancora usato. – Yktula