Originariamente inviato da Ippo343
Non serve, fai due funzioni:
codice:
elem_t* find_element(elem_t* ls, void* key, int (*cmp)(void*, void*));

list_t* find_ListElement(list_t* ls, void* key)
{
    return find_element(ls->head, key, compare);
}
In cui la seconda sulla lista ti fa da wrapper sulla prima.
Ah perfetto, me l'ero immaginata anch'io in questo modo. Pensavo ad una cosa però: in termini di costi computazionali, non risulta essere più efficiente la versione iterativa?

P.S: Che vuol dire che "fa da wrapper sulla prima"?

Nella definizione della struct ci sono dei puntatori a funzione: quei puntatori però devi inizializzarli ad una vera funzione. Altrimenti, che codice potrebbero mai eseguire?
E' un po' come quando dichiari un puntatore ad un intero... poi dovrai pur inizializzarlo a qualche intero. Qui è la stessa cosa: dei puntatori a funzione vanno inizializzati per puntare ad una funzione.
Che stupido che sono...per un qualche oscuro motivo pensavo che si inizializzassero "da sole" nel momento in cui dichiaravo le reali funzioni

Il doppio puntatore serve per essere sicuri che venga inizializzato a NULL in modo da essere più sicuro:
codice:
void free_List(list_t** ls)
{
    procedura_che_elimina_la_lista( *ls ); //(*ls) è un list_t*
    (*ls) = NULL;    //ora il puntatore è a NULL e il programma non esplode se rifai una free
}
Continuo a non capire, ma va beh, ti prendo sulla parola

P.S: Riguardo il metodo corretto per deallocare mi basta richiamare la free sul puntatore alla struct o devo deallocare anche singolarmente la key, il payload? Per le funzioni non c'è nulla da deallocare credo...