2010-11-20 15 views
7

Hii,generica implementazione in C

Mentre stavo implementando alcuni dei programmi per l'assegnazione di classe, appena mi ha colpito come sarebbe per implementare la stessa in modo generico utilizzando C.

I so che abbiamo bisogno di utilizzare i puntatori e le funzioni del vuoto, ma ero solo bloccato su come farlo. Per favore, dammi un esempio che sia semplice e ne dimostri l'uso.

Come il modo di implementare una funzione di confronto per implementare un ordinamento per confronti, o per inserire in una lista collegata in cui ogni nodo ha un elemento di vario tipo ecc ...

PS: Tutti i link ad altre domande o articoli sono utili e benvenuti

+0

Intendi "generici"? http://download.oracle.com/javase/tutorial/extra/generics/index.html –

+2

Si esegue l'aggiornamento a C++ e si utilizzano i modelli, ecco come. – Puppy

+2

@deadMG: so programmare lo stesso utilizzo di generici in C++. Volevo sapere come farlo in C. – Flash

risposta

2

È possibile utilizzare i puntatori void *, quindi molti casting. Tieni presente che dovrai archiviare il tipo in qualche modo per tornare nuovamente all'elemento originale, quindi non è esattamente generico, ma più vicino che puoi ottenere.

Ovviamente questo tipo di codice è molto error-prone

2

Ebbene, ovviamente un modo per parametrizzare tipi è utilizzare il preprocessore, ad esempio:

#define DIVIDE_FUNC(type) divide_##type 
#define DIVIDE_CALL(type, a, b) DIVIDE_FUNC(type)((a), (b)) 
#define DIVIDE_DECL(type) type DIVIDE_FUNC(type)(type a, type b) 
#define DIVIDE_IMPLEMENTATION DIVIDE_DECL(DIVIDE_TYPE) { return a/b; } 

#define DIVIDE_TYPE int 
DIVIDE_IMPLEMENTATION 
#undef DIVIDE_TYPE 
#define DIVIDE_TYPE double 
DIVIDE_IMPLEMENTATION 

#include <stdio.h> 

int main (void) { 
    int i = 5, j = 2; 
    (void) printf("int %d/%d = %d\n", i, j, DIVIDE_CALL(int, i, j)); 
    (void) printf("double %d/%d = %f\n", i, j, DIVIDE_CALL(double, i, j)); 
    return 0; 
} 

Questo implementa due funzioni: divide_double e divide_int. In un esempio più complesso (realistico) l'implementazione potrebbe essere in un file di compilazione separato che è compilato (o incluso) separatamente per ogni tipo con un diverso DIVIDE_TYPE definito.

Lo svantaggio rispetto ai generici reali è che le implementazioni per diversi tipi non vengono generate automaticamente, ovvero DIVIDE_CALL(mytype, x, y) non causa l'implementazione per mytype da generare. (Naturalmente questo potrebbe essere organizzato con uno script relativamente semplice, ma si potrebbe sostenere che non si sta più utilizzando C e ci sono linguaggi con generici predefiniti più carini. =)

In ogni caso, questo può funzionare per strutture di dati e tali in cui è desiderato il tipo di dati effettivo (non un puntatore void *).

+1

Il primo libro C++ di Stroustrup non conteneva modelli. C'era un esempio di come definire un elenco generico usando le macro, era simile al tuo codice. – liori

0

Qualcosa di simile a questo: https://github.com/10098/breakout/tree/master/dl_list/

Si tratta di un'implementazione di una lista doppiamente collegato che ho scritto come un esercizio. Lo uso in un semplice gioco simile a un breakout.

+0

ma come si ottiene il tipo di dati per ciascun nodo? –

+0

Io no. Tutte le routine che eseguono operazioni nell'elenco collegato sono di tipo non -nome. Se qualcuno ha bisogno di qualcosa specifico del tipo, questo può essere fatto attraverso le funzioni di callback che gettano i puntatori void sui tipi necessari e eseguono le operazioni richieste. Non sto dicendo che sia l'approccio migliore, naturalmente. Forse qualcuno mi indicherà un'implementazione migliore. –