Funcție (IT)

De la Wikipedia, enciclopedia liberă.
Salt la navigare Salt la căutare

O funcție (numită și rutină , subrutină , procedură , subrutină sau metodă ), în informatică și în contextul programării , este o construcție sintactică specială a unui limbaj de programare specific care vă permite să grupați, în cadrul unui program , o secvență de instrucțiuni într-un singur bloc, efectuând astfel o operațiune specifică (și în general mai complexă), acțiune (sau prelucrare ) asupra datelor programului în sine, astfel încât, pornind de la anumite intrări , returnează anumite ieșiri .

Importanța, caracterul practic și avantajele unei funcții constă în faptul că poate fi „numită” („reamintită”, „invocată” sau „activată”) în diferite puncte ale programului căruia îi aparține ori de câte ori este nevoie. dacă ar fi o singură instrucțiune fără a fi nevoie să rescrieți de fiecare dată codul relativ, implementând astfel așa-numita reutilizare a codului , la care se adaugă o mai ușoară întreținere a codului în cadrul programului și un design software mai ușor conform filosofiei clasice de divizare și de conducere .

Funcțiile sunt, de asemenea, modurile în care este construit API - ul unui anumit limbaj de programare.

Descriere

O funcție ar trebui să efectueze o anumită operație sau să rezolve o anumită problemă (sau cel puțin întreaga problemă) în cadrul algoritmului soluției, contribuind astfel la factorizarea software - ului . De exemplu, un subrutin conceput pentru a aranja un set de numere întregi în ordine crescătoare poate fi apelat în toate contextele în care această operațiune este utilă sau necesară și compensează lipsa unei „instrucțiuni” reale dedicate scopului, permițând în același timp pentru a descrie algoritmul de sortare corespunzător într-un singur punct al programului.

Subrutinele care implementează funcționalități de bază numite deseori în codul sursă de către programator sunt colectate în așa-numitele biblioteci .

În diferite limbaje de programare , funcțiile sunt implementate în moduri parțial diferite și cu terminologii parțial diferite.

  • termenul de subrutină a fost folosit încă din zorii programării pentru a se referi la secțiuni ale codului de asamblare sau în limbajul mașinii (și este utilizat prin extensie în alte contexte, de exemplu în primele versiuni de BASIC );
  • termenii procedură și funcție sunt în general utilizați în contextul limbajelor de programare la nivel înalt ; acolo unde nu sunt considerate sinonime, o funcție înseamnă un subrutină al cărui scop principal este de a produce o valoare de ieșire pornind de la anumite date de intrare (care stabilește o analogie cu conceptul omonim de funcție matematică ), fără a modifica starea; în timp ce o procedură este un subrutină care nu „produce” nicio valoare de ieșire specială, dar modifică starea. Unele limbi (de exemplu C ) adoptă ca model „standard” cel al funcției și consideră procedurile ca un caz particular al unei funcții care returnează o valoare aparținând setului gol .
  • termenul de subprogram este, de asemenea, tipic limbajelor de programare la nivel înalt și este uneori folosit ca termen general pentru a se referi atât la proceduri, cât și la funcții în sensul descris mai sus.
  • termenul de metodă este folosit în loc de contextul programării orientate pe obiecte în loc de cel al funcției.

Operațiune

Aproape toate limbajele de programare acceptă funcții, oferind propria sintaxă pentru a defini o funcție, adică pentru a scrie codul și una pentru a solicita executarea acestuia (invocarea sau apelarea funcției).

În general, sintaxa comună a unei definiții a funcției oferă:

  • un identificator sau un nume;
  • pentru limbile tastate un tip de returnare sau o specificație privind tipul de date pe care le va returna în ieșire către utilizator sau către alte funcții care îl invocă; atunci când o funcție nu returnează nimic (de ex. funcții cu tip de returnare nul ) funcția va efectua alte prelucrări acționând de exemplu asupra stării variabilelor programului sau afișând ceva pe ecran fără a returna nimic. Cu toate acestea, în limbile netipate sau slab tastate, tipul returnat nu este prezent.
  • specificarea (nu întotdeauna necesară) a așa-numiților parametri sau operanzi ale căror valori vor fi apoi trecute în timpul fazei de invocare și asupra cărora funcția va funcționa în timpul fazei de procesare; chiar și în absența parametrilor, corpul funcției își poate efectua procesarea cu alte instrucțiuni, de exemplu acționând asupra stării variabilelor programului sau afișând ceva pe ecran.
  • corpul funcției sau nucleul procesării constituit de blocul, delimitat în mod adecvat, de una sau mai multe instrucțiuni, fiecare încheiată de comanda de terminare, bucle iterative , structuri condiționale etc., toate încheiate cu variabila revenită în cele din urmă la ieșire. Variabilele definite în bloc vor fi neapărat variabile locale, adică cu vizibilitate numai în interiorul blocului.

O funcție este o bucată de cod care poate fi apelată de oriunde dintr-un program. Pentru invocare este de obicei necesar să reamintim cel puțin numele prin trecerea valorilor oricărui parametru, la care se adaugă alte detalii în funcție de limbajul de programare particularizat în uz (de exemplu notația punctelor în limbaje orientate obiect).

La rândul său, o funcție poate apela o altă funcție, așteptând să se termine. În acest caz vorbim despre funcția de invocare și funcția invocată, sau funcția de apelare și funcția de apelare. De asemenea, este posibil ca o funcție să se numească direct sau indirect. În acest caz, se spune că mai multe instanțe ale aceleiași funcții rulează la un moment dat. Această posibilitate este esențială pentru programarea recursivă .

Executarea acelei părți a programului se oprește până la finalizarea executării unei funcții și continuă din declarația care urmează declarației de invocare.

Un alt instrument, care poate fi folosit uneori în locul unei funcții, deși cu limitări majore, este macro-ul .

Variabile locale

O funcție poate defini variabile, numite locale, care sunt vizibile numai în timpul executării unei anumite instanțe a funcției sau sunt definite și alocate în cadrul blocului sau corpului funcției și sunt alocate la sfârșitul execuției blocului sau funcției în sine. Dacă mai multe instanțe ale unei funcții rulează în același timp, fiecare va avea propria copie a fiecărei variabile locale.

Pentru a cunoaște modalitățile prin care declarațiile făcute local unei funcții pot interacționa cu alte funcții (sau subblocuri de cod), este necesar să aveți o cunoaștere aprofundată a modurilor în care mediul este gestionat de limbajul specific.

Parametri formali și eficienți

Când vorbim despre trecerea parametrilor în sensul adecvat, ne referim la comunicarea directă între funcția apelantă și funcția apelată.

În majoritatea limbilor, parametrii pe care îi poate primi o funcție sunt definiți atunci când funcția este definită. În acest context, variabilele funcționale care se referă la parametrii primiți se numesc parametri formali.

Când se invocă o funcție, identificatorii asociați intern cu valorile care îi sunt transmise se numesc parametri reali sau parametri reali.

Parametrii sunt în mod normal în număr determinat de definiția funcției, dar unele limbi oferă sisteme mai mult sau mai puțin elegante pentru realizarea funcțiilor cu un număr variabil de argumente.

În limbile tastate , tipul de date al parametrilor formali trebuie, de asemenea, să fie definit, iar verificarea tipului trebuie efectuată, de asemenea, pentru a verifica dacă parametrii reali sunt de un tip compatibil cu cel al parametrilor formali corespunzători. Tipul unui parametru poate fi, de asemenea, o structură de date complexă.

Fiecare instanță a unei funcții care rulează la un anumit moment are propria copie a parametrilor reali (și a variabilelor locale).

Deoarece parametrii diferiți ai aceleiași funcții pot fi trecuți prin mecanisme diferite, ne vom referi la parametrul „unul” în următoarele descrieri.

Trecerea parametrilor

Comportamentul unei funcții poate depinde de datele transmise acesteia ca parametri la invocare; în plus, o funcție poate returna datele la ieșire.

Există diferite moduri de a transmite parametrii sau de a accesa structurile definite în cadrul programului în sine: fiecare limbă, de fapt, își gestionează propriul mediu în funcție de regulile de definire pe care le implementează și care trebuie luate în considerare.

Variabile globale

Cea mai simplă metodă de transmitere a parametrilor către o funcție este utilizarea de variabile globale, care sunt vizibile din orice parte a programului. Această practică, atunci când este implementată fără discriminare, este puternic descurajată, deoarece poate duce la o citire semantică slabă a codului, cu consecințe deseori neașteptate. Prin urmare, utilizarea variabilelor globale este considerată o formă necorespunzătoare a parametrilor de trecere.

Trecând după valoare

Cu acest mecanism (în literatura engleză denumită „ pass by value ”) valoarea parametrului real este copiată în variabila funcției apelate care reprezintă parametrul formal. Dacă funcția apelată o modifică, funcția apelantă nu va putea vedea această modificare. Prin urmare, este un pasaj cu sens unic.

Treceți prin adresă sau prin referință

Cu acest mecanism (în literatura engleză denumită „ trece prin referință ”) funcția invocată primește ca parametru un pointer sau o referință la parametrul real. Dacă modificați parametrul transmis de adresă, modificarea va fi vizibilă și pentru funcția de apelare. Pasajul este, prin urmare, potențial bidirecțional.

Treceți după rezultat

Acest mecanism (în literatura engleză denumit „ pass by result ”) este unidirecțional, adică servește pentru a transmite un rezultat apelantului. Ca și în cazul „trecere prin adresă”, funcția invocată primește un pointer sau o referință la parametrul real. Cu toate acestea, acest indicator nu este utilizat pentru a citi valoarea parametrului, ci pentru a copia rezultatul calculat de funcție pe acesta.

Trecerea după valoare și rezultat

Acest mecanism (menționat în literatura engleză ca „ trece prin valoare returnată ” sau „ trece prin valoare-rezultat ”) este o combinație a mecanismelor „trece prin valoare” și „trece prin adresă”. Parametrul este transmis prin adresă, adică funcția apelată primește un pointer sau o referință la parametrul real. Cu toate acestea, în acest caz, funcția face o copie internă a parametrului real și folosește această copie. Înainte de terminare, utilizați adresa parametrului actual pentru a copia conținutul copiei sale interne în parametrul real (practic pentru a returna valoarea către apelant).

Treceți după nume

Acest mecanism (în literatura engleză denumit „ trece prin nume ”), dificil de implementat în limbile compilate, este utilizat în principal în macrocomenzi . Trecerea după nume a fost însă utilizată în ALGOL 68 și în Simula . Spre deosebire de celelalte tipuri de trecere a parametrilor, în care se creează legătura dintre parametrul real și parametrul formal, în acest caz se creează o legătură între parametrul formal și o închidere, formată din parametrul real împreună cu propriul mediu de evaluare, care este fixat în momentul apelului. Mai mult, trebuie remarcat faptul că, cu acest tip de trecere a parametrilor, parametrul real este evaluat de fiecare dată când parametrul formal este întâlnit în timpul execuției.

Treceți prin partajare

Cu acest mecanism (în literatura engleză denumită „ trece prin partajare ”), adoptat de exemplu de Python , apelantul și apelatul împart parametrul real.

Valoare returnată

Pictogramă lupă mgx2.svg Același subiect în detaliu: Întoarcerea (informatică) .

O funcție poate returna o valoare ( tastată ) către apelant. Acest mod de transmitere a datelor este unidirecțional, de la apelant la apelant.

Un apel de funcție este, prin urmare, o expresie , care este evaluată pentru a obține o valoare. Evaluarea unei expresii care conține un apel funcțional duce la executarea funcției.

În unele limbi, termenul procedură indică o funcție fără valoare returnată, în altele se folosește un tip de date specific, numit void , pentru valoarea returnată, ceea ce înseamnă că funcția nu returnează nicio valoare.

În limbile funcționale, tipul de date returnat poate fi o funcție pe care apelantul o poate invoca.

Implementare

În programare, funcțiile sunt un instrument atât de important și răspândit încât necesită o gestionare extrem de eficientă a execuției lor, pentru a menține timpul de apel al funcției și revenirea controlului la programul de apelare redus. Din acest motiv, gestionarea alocării variabilelor locale și trecerea parametrilor sunt în mod normal susținute direct de hardware . Existența stivei în arhitecturi hardware se datorează tocmai nevoii de a sprijini în mod eficient funcțiile. De fapt, atunci când este invocată o funcție, punctul din codul în care a fost invocată este salvat pe stivă (adresa de retur), iar parametrii și variabilele locale ale unei funcții sunt, de asemenea, salvate pe stivă.

Setul acestor date din stivă se numește înregistrare de activare și reprezintă o funcție în timpul rulării, care poate fi suspendată până la finalizarea unei alte funcții care la rândul său a fost invocată.

Înregistrarea de activare la partea de sus a stivei este cea a funcției de executare în prezent, mai jos este cea a funcției pe care a numit -o , și așa mai departe.

Stiva poate fi utilizată și în alte moduri, de exemplu pentru a stoca temporar valori intermediare în evaluarea expresiilor aritmetice.

În asamblare există funcții dedicate susținerii funcțiilor și stivei, cu un corespondent direct în limba mașinii:

  • PUSH: puneți o valoare pe stivă
  • POP: Citiți și eliminați o valoare din stivă
  • JSR: săriți la subrutină, adică săriți la un subrutină (salvând adresa de returnare în stivă cu PUSH)
  • RET: reveniți dintr-un subrutină către apelant (identificat prin efectuarea unui POP al adresei de returnare din stivă)

Desigur, fiecare funcție sau bucată de cod care folosește stiva are responsabilitatea de a elimina tot ce a pus pe stivă înainte de a se termina (și nimic mai mult decât a pus), altfel va fi utilizată valoarea unui parametru sau a unei variabile locale. o adresă de retur, cu consecințe imprevizibile. Dificultatea de a garanta manual această corectitudine este unul dintre motivele care justifică utilizarea limbajelor de nivel înalt , care, printre altele, gestionează automat consistența stivei.

Datorită acestor operații, invocarea unei funcții implică un cost, deși în mod normal modest, în ceea ce privește performanța.

Siguranță

Mecanismul de implementare a funcțiilor, împreună cu aritmetica indicatorilor în limbajul C , este exploatat pentru a crea atacuri de depășire a stivei sau de depășire a tamponului , care vă permit să preluați controlul unui program în execuție oferindu-i date fabricate cu precizie.

Elemente conexe

Alte proiecte

Informatică Portal IT : accesați intrările Wikipedia care se ocupă cu IT