Funzione (informatica): differenze tra le versioni

Contenuto cancellato Contenuto aggiunto
Ho cambiato le parti fondamentali della descrizione
Nessun oggetto della modifica
Etichette: Modifica visuale Modifica da mobile Modifica da web per mobile
 
(46 versioni intermedie di 21 utenti non mostrate)
Riga 1:
{{nota disambigua|un tipo di atto linguistico|Routine (linguistica)|Routine}}
{{F|programmazione|febbraio 2013}}
[[File:Code C.png|thumb|Un programma "[[Hello world]]" in [[linguaggio C]], che contiene la [[funzione main|funzione ''main'']]]]
{{C|argomento=informatica|mese=febbraio 2015|motivo=Non tutti i linguaggi fortemente tipizzati richiedono dichiarazioni di tipo. Cfr. [[Discussione:Funzione (informatica)#Linguaggi fortemente tipati e linguaggi esplicitamente tipati|discussione]].}}
 
Una '''funzione''' (detta anche '''routine''', '''subroutine''', '''procedura''', '''sottoprogramma''' o '''metodo'''), inIn [[informatica]] e nell'ambitoin dellaparticolare nella [[programmazione (informatica)|programmazione]], una '''funzione''' è un particolare costrutto [[sintassi (informatica)|sintattico]]'unità di unorganizzazione determinatodel [[linguaggiocodice di programmazionesorgente|codice]] che permette di raggruppare, all'interno di un [[Programma (informatica)|programma]], una sequenza di [[Istruzione (informatica)|istruzioni]] in un unico blocco, espletandocaratterizzato cosìda unaun specificanome, (edei parametri in generaleingresso più(detti complessaargomenti) operazione,e azioneuno (o più [[Elaborazione dato|dati|elaborazione]]) suirestituiti datiin deluscita. programmaSi stessotratta ineffettivamente mododi taleun'evoluzione che,del aconcetto partire da determinatidi [[input]], restituiscaprocedura determinati [[output(programmazione)|procedura]].<ref>{{Treccani|funzione_res-94b0a5f6-aaa5-11e7-adb0-00271042e8d9_(Enciclopedia-della-Matematica)/}}</ref>
 
L'importanza, la praticità e i vantaggi di una funzione stanno nel fatto che può essere "chiamata" ("richiamata", "invocata" o "attivata") in diversi punti del programma di cui fa parte ogni volta in cui si ha la necessità di farlo come se fosse una singola istruzione senza la necessità di doverne riscrivere ogni volta il relativo [[codice sorgente|codice]] implementando dunque il cosiddetto [[riuso di codice]], cui si aggiunge una più facile [[manutenibilità]] del codice all'interno del programma ede una più facile [[ingegneria del software|progettazione]] del [[software]] secondo la classica filosofia del ''[[Divide et impera (informatica)|divide et impera]]''.
 
== Descrizione ==
Una funzione non serve a nulla.
Quasi tutti i [[linguaggio di programmazione|linguaggi di programmazione]] supportano le funzioni, fornendo una propria sintassi per definire una funzione, ovvero scriverne il codice, e una per richiederne l'esecuzione (invocazione o chiamata della funzione).
In generale la sintassi comune della definizione di una funzione prevede:
 
* un identificativo o nome;
oooh fratellì
* per [[Tipizzazione forte|linguaggi tipizzati]] un [[tipo di ritorno]] ovvero una specifica sul [[tipo di dato]] che essa restituirà in output all'utente o ad altre funzioni che la invocano; quando una funzione non restituisce nulla (per esempio funzioni con tipo restituito <code>void</code>) la funzione avrà svolto altre elaborazioni agendo ad esempio sullo stato delle [[variabile (informatica)|variabili]] del programma o visualizzando a video qualcosa senza restituire nulla. In linguaggi non tipizzati o a [[tipizzazione debole]] invece non è presente il tipo di ritorno.
* la specifica (non sempre necessaria) dei cosiddetti [[Parametro (programmazione)|parametri]] o operandi i cui valori saranno poi passati in fase di invocazione e su cui la funzione opererà in fase di elaborazione; anche in assenza di parametri il corpo della funzione potrà svolgere la sua elaborazione con altre istruzioni ad esempio agendo sullo stato delle variabili del programma o visualizzando a video qualcosa.
* il corpo della funzione ovvero il nucleo dell'elaborazione costituita dal blocco, opportunamente delimitato, di una o più istruzioni, ciascuna terminata dal comando di terminazione, [[iterazione|cicli iterativi]], [[selezione (informatica)|strutture condizionali]] ecc., il tutto concluso con la variabile eventualmente ritornata in output. Variabili definite nel blocco saranno necessariamente variabili locali cioè con visibilità solo all'interno del blocco stesso.
 
=== Identificatore ===
Le funzioni sono tipicamente anche le modalità con cui si costruiscono le [[Application programming interface|API]] di un certo linguaggio di programmazione.
{{Vedi anche|Funzione anonima|Overloading}}
 
Una funzione è una porzione di codice che può essere invocata da qualsiasi punto di un programma. Per l'invocazione occorre tipicamente richiamarne almeno il nome passando i valori degli eventuali parametri, cui si aggiungono eventualmente altri dettagli dipendenti dal particolare linguaggio di programmazione in uso.
==Descrizione==
Una funzione dovrebbe eseguire una determinata operazione o risolvere un determinato problema (o al limite tutto il problema) all'interno dell'[[algoritmo]] risolutivo, contribuendo così alla [[fattorizzazione (software)|fattorizzazione]] del [[software]]. Ad esempio, una subroutine progettata per disporre in ordine crescente un insieme di numeri interi può essere richiamata in tutti i contesti in cui questa operazione sia utile o necessaria, e supplisce alla mancanza di una vera e propria "istruzione" dedicata allo scopo, consentendo al contempo di descrivere il corrispondente [[algoritmo di ordinamento]] in un unico punto del programma.
 
=== Parametri ===
Le subroutine che implementano funzionalità di base spesso richiamate nel [[codice sorgente]] dal programmatore sono raccolte all'interno delle cosiddette [[libreria (informatica)|librerie]].
Generalmente i parametri di una funzione sono definiti all'atto della definizione della stessa. La loro numerosità e il loro ordine è fissato.
Alcuni linguaggi forniscono sistemi più o meno eleganti per realizzare funzioni con un numero variabile di argomenti. In tal caso la funzione si dice "variadica".<ref>{{Cita web|url=http://wpage.unina.it/benerece/LASD-2017/5-Funzioni-a-parametri-variabili.pdf|titolo=Funzioni con numero variabile di parametri: Funzioni Variadiche in C|autore=Massimo Benerecetti|sito=unina.it|accesso=24 marzo 2022|urlarchivio=https://web.archive.org/web/20190711182550/http://wpage.unina.it/benerece/LASD-2017/5-Funzioni-a-parametri-variabili.pdf|urlmorto=no|dataarchivio=11 luglio 2019}}</ref>
 
Nei [[linguaggio tipizzato|linguaggi tipizzati]], anche il [[tipo di dato]] dei parametri formali deve essere definito, e il ''[[type checking]]'' deve essere svolto anche per verificare che i parametri effettivi siano di tipo compatibile con quello dei corrispondenti parametri formali. Il tipo di un parametro può essere anche una complessa [[struttura dati]].
Nei diversi [[linguaggio di programmazione|linguaggi di programmazione]], le funzioni vengono realizzate in modi e con terminologie parzialmente differenti.
 
==== Parametri formali ed effettivi ====
* il termine '''subroutine''' è stato usato fino dagli albori della [[programmazione (informatica)|programmazione]] per riferirsi a sezioni di codice [[assembly]] o in [[linguaggio macchina]] (e viene usato per estensione in altri contesti ad esempio nelle prime versioni del [[BASIC]]);
Le variabili della funzione che fanno riferimento ai parametri ricevuti sono detti parametri formali.
* i termini '''procedura''' e '''funzione''' vengono generalmente usati nel contesto dei [[linguaggio di programmazione ad alto livello|linguaggi di programmazione ad alto livello]]; laddove non siano considerati sinonimi per funzione si intende un sottoprogramma il cui scopo principale sia quello di produrre un valore in output a partire da determinati dati in ingresso (cosa che stabilisce un'analogia con l'omonimo concetto di [[funzione (matematica)|funzione matematica]]), senza modificare lo stato; mentre una procedura è un sottoprogramma che non "produce" alcun particolare valore in output ma modifica lo stato. Alcuni linguaggi (per esempio il [[linguaggio C|C]]) adottano come modello "standard" quello della funzione, e considerano le procedure come caso particolare di funzione che restituisce un valore appartenente all'[[insieme vuoto]].
Quando una funzione viene invocata, gli identificatori associati internamente ai valori che le vengono passati sono detti parametri effettivi o parametri attuali.
* il termine '''sottoprogramma''' è anch'esso tipico dei linguaggi di programmazione ad alto livello, ed è talvolta usato come termine generale per riferirsi sia a procedure che a funzioni nel senso descritto sopra.
* il termine '''[[metodo (informatica)|metodo]]''' è usato invece nell'ambito della [[programmazione orientata agli oggetti]] in luogo di quello di funzione.
 
Ciascuna istanza di una funzione che è in esecuzione in un certo momento possiede la propria copia dei parametri effettivi (e delle variabili locali).
== Funzionamento ==
Quasi tutti i [[linguaggio di programmazione|linguaggi di programmazione]] supportano le funzioni, fornendo una propria sintassi per '''definire''' una funzione, ovvero scriverne il codice, ed una per richiederne l'esecuzione ('''invocazione''' o '''chiamata''' della funzione).
 
==== Passaggio dei parametri ====
In generale la sintassi comune della definizione di una funzione prevede:
Il comportamento di una funzione può essere dipendente dai dati che le sono passati come parametri all'atto dell'invocazione; inoltre una funzione può restituire un dato all'uscita.
* un identificativo o '''nome''';
* per [[Tipizzazione forte|linguaggi tipizzati]] un '''[[tipo di ritorno]]''' ovvero una specifica sul [[tipo di dato]] che essa ritornerà in output all'utente o ad altre funzioni che la invocano; quando una funzione non ritorna nulla (es. ritorno di tipo ''void'') la funzione avrà svolto altre elaborazioni agendo ad esempio sullo stato delle [[variabile (informatica)|variabili]] del programma o visualizzando a video qualcosa senza restituire nulla. In linguaggi non tipizzati o a [[tipizzazione debole]] invece non è presente il tipo di ritorno.
* la specifica (non sempre necessaria) dei cosiddetti '''[[Parametro (programmazione)|parametri]]''' o ''operandi'' i cui valori saranno poi passati in fase di invocazione e su cui la funzione opererà in fase di elaborazione; anche in assenza di parametri il corpo della funzione potrà svolgere la sua elaborazione con altre istruzioni ad esempio agendo sullo stato delle variabili del programma o visualizzando a video qualcosa.
* il '''corpo''' della funzione ovvero il nucleo dell'elaborazione costituita dal blocco, opportunamente delimitato, di una o più istruzioni, ciascuna terminata dal comando di terminazione, [[iterazione|cicli iterativi]], [[selezione (informatica)|strutture condizionali]] ecc., il tutto concluso con la variabile eventualmente ritornata in output. Variabili instanziate o definite nel blocco saranno necessariamente variabili locali cioè con visibilità solo all'interno del blocco stesso.
 
Esistono diverse modalità di passaggio dei parametri, o di accesso alle strutture definite all'interno del programma stesso: ogni linguaggio, infatti, gestisce il proprio [[ambiente (programmazione)|ambiente]] dipendentemente dalle [[Variabile (informatica)#Visibilità di una variabile|regole di ''scoping'']] che implementa, e di cui è necessario tenere conto.
Una funzione è una porzione di codice che può essere invocata da qualsiasi punto di un programma. Per l'invocazione occorre tipicamente richiamarne almeno il nome passando i valori degli eventuali parametri, cui si aggiungono eventualmente altri dettagli dipendenti dal particolare linguaggio di programmazione in uso (es. notazione punto nei linguaggi ad oggetti).
 
==== Passaggio per valore ====
Un funzione può a sua volta richiamare un'altra funzione, restando in attesa che questa termini. Si parla in questo caso di '''funzione invocante''' e '''funzione invocata''', o '''funzione chiamante''' e '''funzione chiamata'''. È anche possibile che una funzione richiami direttamente o indirettamente sé stessa. In questo caso, si dice che in un dato momento sono in esecuzione più '''istanze''' di una stessa funzione. Questa possibilità è essenziale per la [[ricorsione|programmazione ricorsiva]].
Con questo meccanismo il valore del parametro effettivo viene copiato nella variabile della funzione chiamata che rappresenta il parametro formale. Se la funzione chiamata lo modifica, la funzione chiamante non potrà vedere questa modifica. Si tratta quindi di un passaggio unidirezionale.
 
==== Passaggio per riferimento ====
L'esecuzione di quella parte di programma si interrompe fino a quando l'esecuzione di una funzione non è terminata e prosegue dall'istruzione successiva a quella di invocazione.
Con questo meccanismo la funzione invocata riceve come parametro un [[puntatore (programmazione)|puntatore]] o riferimento al parametro effettivo. Se si modifica il parametro passato per indirizzo, la modifica sarà visibile anche alla funzione chiamante. Il passaggio è quindi potenzialmente bidirezionale.
 
=== Valore di ritorno ===
Un altro strumento, che talvolta può essere usato al posto di una funzione, anche se con grosse limitazioni è la [[Macro (informatica)|macro]].
Una funzione può restituire un valore ([[tipo di dato|tipizzato]]) al chiamante. Questa modalità di passaggio di dati è unidirezionale, dal chiamato al chiamante.
 
Una chiamata di funzione è quindi un'[[espressione (informatica)|espressione]], che viene valutata per ottenere un valore. La valutazione di un'espressione che contenga una chiamata di funzione comporta l'esecuzione della funzione stessa.
=== Variabili locali ===
Una funzione può definire variabili, dette locali, che sono visibili solo durante l'esecuzione di ''una particolare istanza'' della funzione ovvero sono istanziate e muoiono all'interno del blocco o corpo della funzione. Se più istanze di una funzione sono in esecuzione contemporaneamente, ciascuna avrà la sua copia di ciascuna variabile locale.
 
In alcuni linguaggi, il termine procedura indica una funzione senza valore di ritorno, in altri si usa un tipo di dato apposito, detto <code>void</code>, per il valore restituito, a significare che la funzione non restituisce alcun valore.
Per conoscere le modalità con cui le dichiarazioni effettuate localmente ad una funzione possano interagire con altre funzioni (o sottoblocchi di codice), è necessario avere una conoscenza approfondita delle modalità con cui l'[[ambiente (programmazione)|ambiente]] viene gestito dallo specifico linguaggio.
 
Nei linguaggi funzionali il tipo di dato restituito può essere una funzione, che il chiamante potrà invocare.
=== Parametri formali ed effettivi ===
Quando si parla di passaggio di parametri in senso proprio, si intende una comunicazione diretta tra la funzione chiamante e la funzione chiamata.
 
== Altre proprietà ==
In gran parte dei linguaggi, i parametri che una funzione può ricevere sono definiti all'atto della definizione della funzione. In questo contesto, le variabili della funzione che fanno riferimento ai parametri ricevuti sono detti '''parametri formali'''.
=== Variabili locali ===
Una funzione può definire variabili, dette locali, che sono visibili solo durante l'esecuzione di una particolare istanza della funzione ovvero sono definite e allocate all'interno del blocco o corpo della funzione e sono deallocate al termine dell'esecuzione del blocco stesso o funzione stessa. Se più istanze di una funzione sono in esecuzione contemporaneamente, ciascuna avrà la sua copia di ciascuna variabile locale.
 
== Implementazione ==
Quando una funzione viene invocata, gli identificatori associati internamente ai valori che le vengono passati sono detti '''parametri effettivi''', dall'[[lingua inglese|inglese]] ''actual parameters'' che a volte viene '''erroneamente''' tradotto con ''parametri attuali''.
=== Supporto nei linguaggi di programmazione ===
Il concetto di funzione è utilizzabile in tutti i [[linguaggi di programmazione]] che implementano il [[programmazione procedurale|paradigma procedurale]].
La maggioranza dei [[linguaggio di programmazione ad alto livello|linguaggi di programmazione ad alto livello]] supporta esplicitamente le funzioni, prevedendo costrutti sintattici dedicati o che in alternativa accorpano diverse varianti del concetto:
 
* i linguaggi influenzati dal [[C (linguaggio di programmazione)|C]] prevedono una sintassi dedicata per le funzioni, che supporta anche le [[procedura (programmazione)|procedure]] come caso particolare;<ref>{{cita|K&R 2007|p. 68}}.</ref>
I parametri sono normalmente in numero determinato dalla definizione della funzione, ma alcuni linguaggi forniscono sistemi più o meno eleganti per realizzare funzioni con un numero variabile di argomenti.
* nei linguaggi fortemente [[programmazione orientata agli oggetti|orientati agli oggetti]], come [[Java (linguaggio di programmazione)|Java]], le funzioni sono disponibili sotto forma di [[metodo (informatica)|metodi]];<ref>
{{Cita web|url=https://www.w3schools.com/java/java_methods.asp|titolo=Java Methods|accesso=2024-03-25|lingua=en}}</ref><ref>{{Cita web|url=https://docs.oracle.com/javase/tutorial/java/javaOO/methods.html|titolo=Defining Methods|accesso=2024-03-25|lingua=en}}</ref>
 
* nei [[IEC 61131-3|linguaggi per l'automazione industriale]] le funzioni sono disponibili anche sotto forma di [[Function block diagram|blocchi funzionali]].<ref>{{Cita|Basile, Chiacchio 2004|cap. 2.3}}.</ref>
Nei [[linguaggio tipizzato|linguaggi tipizzati]], anche il [[tipo di dato]] dei parametri formali deve essere definito, ed il [[type checking]] deve essere svolto anche per verificare che i parametri effettivi siano di tipo compatibile con quello dei corrispondenti parametri formali. Il tipo di un parametro può essere anche una complessa [[struttura dati]].
 
Alcuni linguaggi tendono a utilizzare terminologie diverse:
Ciascuna istanza di una funzione che è in esecuzione in un certo momento possiede la propria copia dei parametri effettivi (e delle variabili locali).
 
* il termine subroutine è stato usato fino dagli albori della [[programmazione (informatica)|programmazione]] per riferirsi a sezioni di codice [[Linguaggio assembly|assembly]] o in [[linguaggio macchina]] (e viene usato per estensione in altri contesti ad esempio nelle prime versioni del [[BASIC]]);
Poiché parametri diversi di una stessa funzione possono essere passati con meccanismi diversi, nelle descrizioni seguenti si farà riferimento a "un" parametro.
* il termine "sottoprogramma" è anch'esso tipico dei linguaggi di programmazione ad alto livello, ed è talvolta usato come termine generale per riferirsi sia a procedure che a funzioni.
 
=== PassaggioSupporto di parametrihardware ===
Nella programmazione le funzioni sono uno strumento talmente importante e diffuso da richiedere una gestione della loro esecuzione estremamente efficiente allo scopo di mantenere bassi i tempi di chiamata della funzione e di ritorno del controllo al programma chiamante. Per questo motivo la gestione dell'allocazione delle variabili locali e del passaggio dei parametri vengono normalmente supportate direttamente dall'[[hardware]]. L'esistenza dello [[Pila (informatica)|stack]] nelle architetture hardware è appunto riconducibile alla necessità di supportare efficientemente le funzioni. Infatti, quando viene invocata una funzione il punto del codice in cui è stata invocata viene salvato sullo stack (indirizzo di ritorno), e anche i parametri e le variabili locali di una funzione vengono salvati sullo stack.
 
L'insieme di questi dati sullo stack è detto ''record'' di attivazione, e rappresenta una funzione in fase di esecuzione, che può essere sospesa in attesa del completamento di un'altra funzione che a sua volta ha invocato.
Il comportamento di una funzione può essere dipendente dai dati che le sono passati come '''parametri''' all'atto dell'invocazione; inoltre una funzione può restituire un dato all'uscita.
 
Il ''record'' di attivazione in cima allo stack è quello della funzione attualmente in esecuzione, sotto c'è quello della funzione che l'ha chiamata, e così via.
Esistono diverse modalità di passaggio dei parametri, o di accesso alle strutture definite all'interno del programma stesso: ogni linguaggio, infatti, gestisce il proprio [[ambiente (programmazione)|ambiente]] dipendentemente dalle [[Variabile (informatica)#Visibilità di una variabile|regole di scoping]] che implementa, e di cui è necessario tenere conto.
 
Lo stack può essere usato anche in altri modi, ad esempio per memorizzare temporaneamente valori intermedi nella valutazione delle espressioni aritmetiche.
==== Variabili globali ====
Il metodo più semplice di passare parametri ad una funzione è l'utilizzo di [[variabile (informatica)|variabili]] globali, ovvero visibili da qualsiasi parte del programma. Questa pratica, quando attuata indiscriminatamente, è fortemente scoraggiata, perché può portare ad una scarsa leggibilità semantica del codice, con conseguenze spesso inaspettate. Pertanto l'uso di variabili globali viene considerata una forma impropria di passaggio di parametri.
 
In [[assembly]] esistono istruzioni dedicate al supporto delle funzioni e dello stack, con un corrispondente diretto nel linguaggio macchina:
==== Passaggio per valore ====
* {{Codice|codice=PUSH|linguaggio=asm}}: metti un valore sullo [[Pila (informatica)|stack]]
Con questo meccanismo (nella letteratura in inglese indicato come "''pass by value''") il '''valore''' del parametro effettivo viene copiato nella variabile della funzione chiamata che rappresenta il parametro formale. Se la funzione chiamata lo modifica, la funzione chiamante non potrà vedere questa modifica. Si tratta quindi di un passaggio unidirezionale.
* {{Codice|codice=POP|linguaggio=asm}}: leggi e togli dallo stack un valore
* {{Codice|codice=JSR|linguaggio=asm}}: ''jump to subroutine'', ovvero salta a una subroutine (salvando l'indirizzo di ritorno sullo stack con {{Codice|codice=PUSH|linguaggio=asm}})
* {{Codice|codice=RET|linguaggio=asm}}: ritorno da una subroutine al chiamante (identificato eseguendo una {{Codice|codice=POP|linguaggio=asm}} dell'indirizzo di ritorno dallo stack)
 
Naturalmente, ciascuna funzione o pezzo di codice che usa lo stack ha la responsabilità di togliere tutto quello che ha messo sullo stack prima di terminare (e nulla più di quanto ha messo), altrimenti il valore di un parametro o di una variabile locale verrà impiegato come indirizzo di ritorno, con conseguenze impredicibili. La difficoltà di garantire manualmente questa correttezza è uno dei motivi che giustificano l'uso di [[Linguaggio di programmazione ad alto livello|linguaggi di alto livello]], che tra l'altro gestiscono automaticamente la coerenza dello stack.
==== Passaggio per indirizzo o per riferimento ====
Con questo meccanismo (nella letteratura in inglese indicato come "''pass by reference''") la funzione invocata riceve come parametro un [[puntatore (programmazione)|puntatore]] o riferimento al parametro effettivo. Se modifica il parametro passato per indirizzo, la modifica sarà visibile anche alla funzione chiamante. Il passaggio è quindi potenzialmente bidirezionale.
 
A causa di queste operazioni, l'invocazione di una funzione comporta un costo, seppur normalmente modesto, in termini di prestazioni.
==== Passaggio per risultato ====
Questo meccanismo (nella letteratura in inglese indicato come "''pass by result''") è unidirezionale, serve cioè a passare un risultato al chiamante. Come nel caso del "passaggio per indirizzo", la funzione invocata riceve un [[puntatore (programmazione)|puntatore]] o riferimento al parametro effettivo. Questo puntatore viene però usato non per leggere il valore del parametro, ma per copiarvi il risultato calcolato dalla funzione.
 
== Utilizzi ==
==== Passaggio per valore e risultato ====
=== Riuso di codice ===
Questo meccanismo (nella letteratura in inglese indicato come "''pass by value-returned''" o "''pass by value-result''") è una combinazione dei meccanismi di "passaggio per valore" e "passaggio per indirizzo". Il parametro è passato per indirizzo, cioè la funzione chiamata riceve un puntatore o riferimento al parametro effettivo. Tuttavia, in questo caso, la funzione fa una copia interna del parametro effettivo e usa questa copia. Prima di terminare, usa l'indirizzo del parametro effettivo per copiare il contenuto della sua copia interna sul parametro effettivo (in pratica per restituire il valore al chiamante).
{{Vedi anche|Riuso di codice}}
 
Una funzione dovrebbe eseguire una determinata operazione o risolvere un determinato problema (o al limite tutto il problema) all'interno dell'[[algoritmo]] risolutivo, contribuendo così alla [[fattorizzazione (software)|fattorizzazione]] del [[software]]. Ad esempio, una subroutine progettata per disporre in ordine crescente un insieme di numeri interi può essere richiamata in tutti i contesti in cui questa operazione sia utile o necessaria, e supplisce alla mancanza di una vera e propria "istruzione" dedicata allo scopo, consentendo al contempo di descrivere il corrispondente [[algoritmo di ordinamento]] in un unico punto del programma.
==== Passaggio per nome ====
Questo meccanismo (nella letteratura in inglese indicato come "''pass by name''"), di difficile realizzazione nei linguaggi compilati, è soprattutto usato nelle [[Macro (informatica)|macro]]. Il passaggio per nome è tuttavia stato usato nell'[[ALGOL|ALGOL 68]] e nel [[Simula]]. A differenza degli altri tipi di passaggio di parametro, in cui viene creato il legame tra il parametro effettivo ed il parametro formale, in questo caso si crea un legame tra il parametro formale ed una chiusura, formata dal parametro effettivo insieme al proprio ambiente di valutazione, che è fissato al momento della chiamata. Inoltre bisogna fare attenzione che con questo tipo di passaggio di parametro, il parametro effettivo viene valutato ogni volta che il parametro formale viene incontrato durante l'esecuzione.
 
Le subroutine che implementano funzionalità di base spesso richiamate nel [[codice sorgente]] dal programmatore sono raccolte all'interno delle cosiddette [[Libreria (software)|librerie]].
==== Passaggio per condivisione ====
Con questo meccanismo (nella letteratura in inglese indicato come "''pass by sharing''"), adottato ad esempio dal [[Python]], chiamante e chiamato condividono il parametro effettivo.
 
=== Valore restituitoHacking ===
{{vediVedi anche|ReturnArbitrary (informatica)code execution}}
Una funzione può restituire un valore ([[tipo di dato|tipizzato]]) al chiamante. Questa modalità di passaggio di dati è unidirezionale, dal chiamato al chiamante.
 
Il meccanismo di implementazione delle funzioni, insieme all'aritmetica dei puntatori nel [[linguaggio C]], viene sfruttato per costruire attacchi di tipo ''[[stack overflow]]'' o ''[[buffer overflow]]'', che permettono di prendere il controllo di un programma in esecuzione fornendogli dati accuratamente artefatti.
Una chiamata di funzione è quindi un'[[espressione (informatica)|espressione]], che viene valutata per ottenere un valore. La valutazione di una espressione che contenga una chiamata di funzione comporta l'esecuzione della funzione stessa.
 
== Note ==
In alcuni linguaggi, il termine '''procedura''' indica una funzione senza valore di ritorno, in altri si usa un tipo di dato apposito, detto<code>void</code>, per il valore restituito, a significare che la funzione non restituisce alcun valore.
<references />
 
== Bibliografia ==
Nei linguaggi funzionali il tipo di dato restituito può essere una funzione, che il chiamante potrà invocare.
* {{Cita libro|autore=[[Brian W. Kernighan]]|autore2=[[Dennis M. Ritchie]]|traduttore=Valerio Marra|titolo=Il linguaggio C|edizione=2|editore=Pearson|anno=2007|ISBN=978-88-7192-200-3|cid= K&R 2007}}
 
* {{Cita libro|titolo=Tecnologie informatiche per l'automazione|autore=Francesco Basile|autore2=Pasquale Chiacchio|edizione=2|editore=McGraw-Hill|città= Milano|anno=2004|ISBN=88-386-6147-2|cid= Basile, Chiacchio 2004}}
== Implementazione delle funzioni ==
Nella programmazione le funzioni sono uno strumento talmente importante e diffuso da richiedere una gestione della loro esecuzione estremamente efficiente allo scopo di mantenere bassi i tempi di chiamata della funzione e di ritorno del controllo al programma chiamante. Per questo motivo la gestione dell'allocazione delle variabili locali e del passaggio dei parametri vengono normalmente supportate direttamente dall'[[hardware]]. L'esistenza dello [[stack]] nelle architetture hardware è appunto riconducibile alla necessità di supportare efficientemente le funzioni. Infatti, quando viene invocata una funzione il punto del codice in cui è stata invocata viene salvato sullo stack ('''indirizzo di ritorno'''), e anche i parametri e le variabili locali di una funzione vengono salvati sullo stack.
 
L'insieme di questi dati sullo stack è detto '''record di attivazione''', e rappresenta una funzione in fase di esecuzione, che può essere sospesa in attesa del completamento di un'altra funzione che a sua volta ha invocato.
 
Il record di attivazione in cima allo stack è quello della funzione attualmente in esecuzione, sotto c'è quello della funzione che l'ha chiamata, e così via.
 
Lo stack può essere usato anche in altri modi, ad esempio per memorizzare temporaneamente valori intermedi nella valutazione delle espressioni aritmetiche.
 
In [[assembly]] esistono funzioni dedicate al supporto delle funzioni e dello stack, con un corrispondente diretto nel linguaggio macchina:
* PUSH: metti un valore sullo [[stack]]
* POP: leggi e togli dallo stack un valore
* JSR: jump to subroutine, ovvero salta ad una subroutine (salvando l'indirizzo di ritorno sullo stack con PUSH)
* RET: ritorno da una subroutine al chiamante (identificato eseguendo una POP dell'indirizzo di ritorno dallo stack)
 
Naturalmente, ciascuna funzione o pezzo di codice che usa lo stack ha la responsabilità di togliere tutto quello che ha messo sullo stack prima di terminare (e nulla più di quanto ha messo), altrimenti il valore di un parametro o di una variabile locale verrà impiegato come indirizzo di ritorno, con conseguenze impredicibili. La difficoltà di garantire manualmente questa correttezza è uno dei motivi che giustificano l'uso di [[Linguaggio di programmazione ad alto livello|linguaggi di alto livello]], che tra l'altro gestiscono automaticamente la coerenza dello stack.
 
A causa di queste operazioni, l'invocazione di una funzione comporta un costo, seppur normalmente modesto, in termini di prestazioni.
 
=== Sicurezza ===
Il meccanismo di implementazione delle funzioni, insieme all'aritmetica dei puntatori nel [[linguaggio C]], viene sfruttato per costruire attacchi di tipo [[stack overflow]] o [[buffer overflow]], che permettono di prendere il controllo di un programma in esecuzione fornendogli dati accuratamente artefatti.
 
== Voci correlate ==
{{Div col}}
* [[Entry point]]
* [[Punto d'ingresso]]
* [[Funzione variadica]]
* [[Funzione anonima]]
Riga 130 ⟶ 121:
* [[Programmazione (informatica)]]
* [[Programmazione procedurale]]
* [[StackPila (informatica)]]
* [[Macro (informatica)]]
{{Div col end}}
 
== Altri progetti ==
{{Interprogetto|etichetta=funzione|wikt=funzione}}
 
== Collegamenti esterni ==
* {{Collegamenti esterni}}
* {{FOLDOC|function|function}}
 
{{Portale|Informatica}}