Salve,
qualcuno saprebbe dirmi nello specifico cosa fanno ambedue le dchiarazioni e quindi la differenza tra una e l'altra funzione?
Vi ringrazio in anticipo,codice:int ( *compare )( int a, int b ) int *compare( int a, int b )
Neptune.
Salve,
qualcuno saprebbe dirmi nello specifico cosa fanno ambedue le dchiarazioni e quindi la differenza tra una e l'altra funzione?
Vi ringrazio in anticipo,codice:int ( *compare )( int a, int b ) int *compare( int a, int b )
Neptune.
"Estremamente originale e fantasioso" By darkiko;
"allora sfiga crepuscolare mi sa che e' meglio di atmosfera serale" By NyXo;
"per favore, già è difficile con lui" By fcaldera;
"se lo apri te e invece di "amore" ci metti "lavoro", l'effetto è lo stesso" By fred84
Tra l'altro nell'esercizio lo utilizza in questo modo:
Questi sono i prototipi delle funzioni:
codice:void bubble( int work[], const int size, int (*compare)( int a, int b ) ); int ascending( int a, int b ); int descending( int a, int b );
Questa è invece una chiamata a funzione:
Questa è la dichiarazione delle funzioni ma credo che sia "marginale" come vengono dichiarate a questo punto:codice:bubble( a, SIZE, ascending );
codice:void bubble( int work[], const int size, int (*compare)( int a, int b ) ) { int pass; /* pass counter */ int count; /* comparison counter */ void swap( int *element1Ptr, int *element2ptr ); /* prototype */ /* loop to control passes */ for ( pass = 1; pass < size; pass++ ) { /* loop to control number of comparisons per pass */ for ( count = 0; count < size - 1; count++ ) { /* if adjacent elements are out of order, swap them */ if ( (*compare)( work[ count ], work[ count + 1 ] ) ) { swap( &work[ count ], &work[ count + 1 ] ); } /* end if */ } /* end for */ } /* end for */ } /* end function bubble */ /* swap values at memory locations to which element1Ptr and element2Ptr point */ void swap( int *element1Ptr, int *element2Ptr ) { int hold; /* temporary holding variable */ hold = *element1Ptr; *element1Ptr = *element2Ptr; *element2Ptr = hold; } /* end function swap */ /* determine whether elements are out of order for an ascending order sort */ int ascending( int a, int b ) { return b < a; /* swap if b is less than a */ } /* end function ascending */ /* determine whether elements are out of order for a descending order sort */ int descending( int a, int b ) { return b > a; /* swap if b is greater than a */ }
"Estremamente originale e fantasioso" By darkiko;
"allora sfiga crepuscolare mi sa che e' meglio di atmosfera serale" By NyXo;
"per favore, già è difficile con lui" By fcaldera;
"se lo apri te e invece di "amore" ci metti "lavoro", l'effetto è lo stesso" By fred84
Puntatore ad una funzione che restituisce un int e accetta due intcodice:int ( *compare )( int a, int b )
Funzione che restituisce un puntatore ad int e accetta due intcodice:int *compare( int a, int b )
No MP tecnici (non rispondo nemmeno!), usa il forum.
Cioè il secondo caso, ovvero questo:Originariamente inviato da oregon
Puntatore ad una funzione che restituisce un int e accetta due intcodice:int ( *compare )( int a, int b )
Funzione che restituisce un puntatore ad int e accetta due intcodice:int *compare( int a, int b )
Mi sembra il più banale, ovvero è una semplice funzione che, passandogli due interi, restituisce come risultato un puntatore, ovvero ci sarà come ritorno uncodice:int *compare( int a, int b )
Giusto?codice:return *puntatore;
Il secondo caso invece non mi è molto chiaro, come fa un puntatore a puntare ad una funzione, a cosa punta? potresti farmi un esempio pratico?
"Estremamente originale e fantasioso" By darkiko;
"allora sfiga crepuscolare mi sa che e' meglio di atmosfera serale" By NyXo;
"per favore, già è difficile con lui" By fcaldera;
"se lo apri te e invece di "amore" ci metti "lavoro", l'effetto è lo stesso" By fred84
Un puntatore a funzione è una variabile che contiene l'indirizzo di una funzione, che tramite esso può essere richiamata. È utilizzato dal codice che hai riportato per permettere al chiamante di fornire una sua funzione di confronto personalizzata; la chiamata della funzione in questione la trovi alla riga
dalla sintassi apparentemente contorta ma coerente con la sintassi solita dei puntatori: il puntatore a funzione viene dereferenziato, consentendo così la chiamata a funzione.codice:if ( (*compare)( work[ count ], work[ count + 1 ] ) ) {
Tendenzialmente comunque si cerca di evitare di specificare i parametri di tipo puntatore a funzione in quella maniera perché sono abbastanza illeggibile; di solito infatti si usano dei typedef per renderli un po' meno ostici.
I puntatori a funzione, oltre che per situazioni come questa, si usano moltissimo per consentire al chiamante di specificare una funzione di callback, per esempio per notificarlo dell'avanzamento di un'operazione o del verificarsi di un evento.
Amaro C++, il gusto pieno dell'undefined behavior.
Riguardando il codice effettivamente ero riuscito a capirlo, particamente così facendo puoi passare nel parametro "puntatore" una funzione, e magari, scegliere di volta in volta che funzione passargli come parametro.Originariamente inviato da MItaly
Un puntatore a funzione è una variabile che contiene l'indirizzo di una funzione, che tramite esso può essere richiamata. È utilizzato dal codice che hai riportato per permettere al chiamante di fornire una sua funzione di confronto personalizzata; la chiamata della funzione in questione la trovi alla riga
dalla sintassi apparentemente contorta ma coerente con la sintassi solita dei puntatori: il puntatore a funzione viene dereferenziato, consentendo così la chiamata a funzione.codice:if ( (*compare)( work[ count ], work[ count + 1 ] ) ) {
Tendenzialmente comunque si cerca di evitare di specificare i parametri di tipo puntatore a funzione in quella maniera perché sono abbastanza illeggibile; di solito infatti si usano dei typedef per renderli un po' meno ostici.
I puntatori a funzione, oltre che per situazioni come questa, si usano moltissimo per consentire al chiamante di specificare una funzione di callback, per esempio per notificarlo dell'avanzamento di un'operazione o del verificarsi di un evento.
Ho visto un esempio, molto più capibile, che implementavano questo passaggio di puntatore a funzione per l'utilizzo in un menù:
Praticamente era il classico ciclo while che a seconda della scelta del menù richiamava una funzione, però in realtà si richiamava "un vettore di puntatori a funzione" e la scelta del menù era l'indice di questo vettore.
Nel caso citato prima invece non riuscivo a capirne il nesso perchè aveva veramente poco senso la cosa. Secondo me bisognerebbe spiegare le potenzialità di una funzione mostrandone l'utilizzo per "un azione" che non si potrebbe fare in altro modo. Mostrare la via più complicata di una cosa semplice diventa illogico e quindi difficile da capire.
"Estremamente originale e fantasioso" By darkiko;
"allora sfiga crepuscolare mi sa che e' meglio di atmosfera serale" By NyXo;
"per favore, già è difficile con lui" By fcaldera;
"se lo apri te e invece di "amore" ci metti "lavoro", l'effetto è lo stesso" By fred84
Ha così poco senso che anche la funzione di libreria C per l'ordinamento (qsort) usa lo stesso approccio...Originariamente inviato da Neptune
Nel caso citato prima invece non riuscivo a capirne il nesso perchè aveva veramente poco senso la cosa. Secondo me bisognerebbe spiegare le potenzialità di una funzione mostrandone l'utilizzo per "un azione" che non si potrebbe fare in altro modo. Mostrare la via più complicata di una cosa semplice diventa illogico e quindi difficile da capire.
Seriamente, nelle operazioni di ordinamento è fondamentale consentire al chiamante di specificare una funzione di confronto: l'algoritmo infatti è sempre lo stesso, indifferentemente dal criterio scelto per l'ordinamento, e in questa maniera anche se voglio ordinare il mio insieme per qualche criterio strano (ordine ascendente, discendente, distanza da un certo numero, ...) posso farlo.
Amaro C++, il gusto pieno dell'undefined behavior.
Allora devo prenderci la mano, perchè devo ammettere di non aver mai fatto un puntatore ad una funzione.Originariamente inviato da MItaly
Ha così poco senso che anche la funzione di libreria C per l'ordinamento (qsort) usa lo stesso approccio...
Seriamente, nelle operazioni di ordinamento è fondamentale consentire al chiamante di specificare una funzione di confronto: l'algoritmo infatti è sempre lo stesso, indifferentemente dal criterio scelto per l'ordinamento, e in questa maniera anche se voglio ordinare il mio insieme per qualche criterio strano (ordine ascendente, discendente, distanza da un certo numero, ...) posso farlo.
"Estremamente originale e fantasioso" By darkiko;
"allora sfiga crepuscolare mi sa che e' meglio di atmosfera serale" By NyXo;
"per favore, già è difficile con lui" By fcaldera;
"se lo apri te e invece di "amore" ci metti "lavoro", l'effetto è lo stesso" By fred84
E' anche vero però che la funzione qsort() utilizza i puntatori a void per rendere *effettivamente* generico l'algoritmo di ordinamento, cioè tale da poter ordinare array di qualsiasi tipo (anche array di strutture definite dall'utente) semplicemente passando come parametro una funzione che "istruisca" la qsort() su come operare i confronti.Originariamente inviato da MItaly
Ha così poco senso che anche la funzione di libreria C per l'ordinamento (qsort) usa lo stesso approccio...
Seriamente, nelle operazioni di ordinamento è fondamentale consentire al chiamante di specificare una funzione di confronto: l'algoritmo infatti è sempre lo stesso, indifferentemente dal criterio scelto per l'ordinamento, e in questa maniera anche se voglio ordinare il mio insieme per qualche criterio strano (ordine ascendente, discendente, distanza da un certo numero, ...) posso farlo.
Nell'esempio postato dal nostro amico questo viene a mancare perché la funzione parametro riceve in input due interi, e non genericamente due puntatori void. La cosa vuole semplicemente servire a far scegliere all'utente il tipo di ordinamento (crescente o decrescente) ma in effett in quel caso i puntatori a funzione non sono poi tanto utili... magari con un semplice parametro booleano si poteva risolvere la cosa: 0 -> ordinamento crescente; 1 -> ordinamento decrescente. Poi sarebbe bastato differenziare i casi all'interno della funzione stessa. Voleva essere forse solo un semplice esempio di utilizzo dei puntatori a funzione, sebbene in una situazione in cui potevano essere evitati.
every day above ground is a good one
Certo, infatti a questo punto la possibilità è limitata a diversi generi di ordinamento tra interi, per cui tra gli esempi che ho citato se noti ho messo giusto ordine ascendente, discendente e (un po' più esoterico) ordine di distanza da un altro numero; potrei aggiungere, che so, un ordinamento che metta prima i numeri pari e poi i dispari, oppure un ordinamento che confronti il valore assoluto dei numeri; un callback di questo genere ti dà comunque una certa flessibilità (che ovviamente non è quella della generica funzione qsort).
Per inciso, per questo genere di cose è comunque stato dimostrato che i template C++ e i suoi functori battono i puntatori a funzioni C in grande stile, sia per eleganza (dal momento che il functore può accettare direttamente il tipo corretto senza bisogno di fare mille cast da void *) che per velocità. Infatti il codice di un functore passato come argomento template può essere messo inline dal compilatore all'interno dell'algoritmo di ordinamento, tagliando sull'overhead della chiamata a funzione mediante puntatore, il che sui grandi numeri si sente, visto che spesso la funzione di confronto è composta praticamente da una singola istruzione.
Amaro C++, il gusto pieno dell'undefined behavior.