Documente Academic
Documente Profesional
Documente Cultură
Cursul nr. 9
FUNCII N C/C++
Definiii de funcii Declaraii de funcii. Prototipuri. Transferul datelor prin parametri Transfer prin valoare. Conversii de tip. Transfer prin adres Transferul prin variabile referin Rezultatul unei funcii. Instruciunea return Funcii recursive Pointeri de funcii Parametri cu valori implicite Supradefinirea (suprancrcarea) funciilor Funcii inline
Funcii n C/C++
n limbajele C/C++ programul este o colecie de module distincte numite funcii, structura general a programului fiind: <directive preprocesor> <declaraii globale> funcii Un program C++ conine obligatoriu o funcie numit main() i aceasta este apelat la lansarea n execuie a programului. Programul surs poate fi partiionat n mai multe fiiere grupate ntr-un proiect. Fiecare fiier conine declaraii globale i un set de funcii, dar numai unul conine funcia main(). O funcie este un bloc de instruciuni care are un nume, poate prelua date de intrare (parametri) i poate ntoarce un obiect (rezultat).
12/13/2010
Definiii de funcii
Sintaxa definiiei unei funcii este: tip nume_funcie (<lista_parametri>) { <declaraii locale> secven de instruciuni } unde: tip este un tip oarecare de dat i reprezint tipul rezultatului returnat de funcie. Dac nu este specificat, implicit tipul rezultatului returnat este int. Pentru funciile care nu returneaz rezultat trebuie s se specifice tipul void. nume_functie este un identificator. lista_parametri reprezint enumerarea declaraiilor parametrilor sub forma:
tip_parametru nume_parametru, <tip_parametru nume_parametru>
Definiii de funcii
Nu este admis definirea unei funcii n blocul altei funcii i nu sunt permise salturi cu instruciunea goto n afara funciei. Apelul funciei: nume_functie ( lista_parametri_efectivi); Att la definirea, ct i la apelul funciilor, parantezele () urmeaz ntotdeauna numele funciilor, chiar dac acestea nu au parametri formali. Se folosete denumirea de parametri formali pentru identificatorii din lista de argumente din definiia funciei i parametri efectivi (constantele, variabilele, expresiile) din lista unui apel al funciei. Parametrii formali reprezint variabile locale care au ca domeniu de folosire funcia i timpul de via corespunde duratei de execuie a funciei, deci valorile lor se memoreaz n stiv sau n regitrii procesorului.
12/13/2010
12/13/2010
Parametri efectivi
12/13/2010
Pentru ca o funcie s poat modifica valoarea unei variabile folosit ca parametru efectiv, trebuie folosit un parametru formal de tip pointer. Astfel se transmite adresa obiectului i prin indirectare se poate opera asupra obiectului folosit la apelul funciei ca parametru efectiv. La apelul funciei se va folosi ca parametru efectiv adres de variabil. n mod frecvent se folosete transfer prin adres n cazul funciilor care au ca parametri tablouri de date. Tablourile conin o cantitate mare de date al cror transfer prin valoare ar avea ca efect o scdere a vitezei de execuie i cretere a memoriei necesare prin copierea valorilor n variabile locale, astfel c se transfer doar adresa la care sunt alocate.
12/13/2010
Folosirea parametrilor formali variabile referin este similar folosirii parametrilor formali pointeri, asigurnd posibilitatea de a modifica valorile parametrilor efectivi. Utilizarea referinelor prezint avantajul c procesul de transfer prin referin este efectuat de compilator n mod transparent, scrierea funciei i apelul ei fiind simplificate. Dac tipul parametrului efectiv nu coincide cu cel al parametrului formal referin, compilatorul efectueaz o conversie, ca n cazul transferului prin valoare. Pentru realizarea conversiei se creeaz un obiect temporar de dimensiunea tipului referin, n care se nscrie valoarea convertit a parametrului efectiv, parametrul formal referin fiind asociat obiectului temporar. Se pierd astfel avantajele folosirii referinelor ca parametri formali.
Transfer prin valoare Definiiile funciilor: void schimba(int a, int b) { int temp ; temp = a; a = b; b = temp; } Apelul funciilor int p, q; schimba(p, q);
void schimba(int *a, int *b) { int temp ; temp = *a; *a = *b; *b = temp; }
12/13/2010
Transferul prin adres sau referin nu este util doar n cazul n care se dorete modificarea din interiorul unei funcii a unor obiecte definite n funcia apelant, ci i atunci cnd, obiectele transferate ca parametri nglobeaz cantitate mare de date i se dorete eficientizarea codului prin folosirea a unei cantiti ct mai mici de memorie i creterea vitezei de execuie. Dac se dorete protejarea datelor folosite ca parametri, parametrii vor fi declarai const.
12/13/2010
Funcii recursive
O funcie este numit funcie recursiv dac ea se autoapeleaz, fie direct (n definiia ei se face apel la ea nsi), fie indirect (prin apelul altor funcii). Pentru fiecare apel al funciei, parametrii i variabilele automatice se memoreaz pe stiv, avnd valori distincte. Orice apel al unei funcii conduce la o revenire n funcia respectiv, n punctul urmtor instruciunii de apel. La revenirea dintr-o funcie, stiva este curat (stiva revine la starea dinaintea apelului). Un exemplu de funcie recursiv este funcia de calcul a factorialului (n!), definit astfel: fact(n) = 1, dac n=0; fact(n) = n*fact(n-1), dac n>0;
12/13/2010
Funcii recursive
Este important ca la execuia funciei s se asigure ieirea din recursivitate.
double fact(int n) { if (n<0) // valorile negative sunt invalide { printf("\nParametru negativ !"); getch(); exit(2); } if (n == 0) return 1; else return n*fact(n-1); }
Pointeri de funcii
Limbajele C/C++ permit operarea cu variabile pointer care conin adresa de nceput a codului executabil al unei funcii. Aceste variabile permit: transferul ca parametru al adresei funciei asociate; apelul funciei prin intermediul pointerului. Declaraia pointerilor de funcii se face cu sintaxa: tip_r(*p_fct)(<lista_tip_param>); unde p_fct se declar ca pointer pentru funcie cu rezultat de tip tip_r i parametri lista_tip_param. n urma declaraiei p_fact va putea fi folosit pentru a apela funcia, folosind sintaxa: p_fct(lista_parametri_efectivi);
12/13/2010
Pointeri de funcii
# include <stdio.h> int fct(int, float); void main() { int (*p_f)(int, float); int i = 5, j; float r = 3.5; p_f = fct; j = p_f(i, r); printf(\nj = %d, j); } int fct(int a, float b) { printf(\na = %d, a); printf(\nb = %f, b); return ( a + (int)b ); } // prototip de funcie
// se atribuie adresa funciei fct pointerului p_f // se apeleaz funcia fct prin pointerul p_f
void main() { printf(Apel normal : f( 5, 10)\n; f( 5, 10); printf(Apel cu un singur parametru: f( 5 )\n); f( 5 ); } void f(int a, int b) { printf(\n a = %d, b = %d, a, b); }
10
12/13/2010
La declararea i definirea funciilor cu parametri implicii, trebuie s se respecte urmtoarele reguli: Valorile implicite se specific o singur dat, fie n prototip, fie n antetul definiiei. De obicei acestea se declar n prototipul funciei, funciile putnd fi definite n alt fiier. n lista de parametri, cei cu valori implicite trebuie s fie plasai la sfritul listei. Aceast regul permite identificarea univoc a valorilor implicite. La apelul funciei, lista de argumente efective va cuprinde obligatoriu valori pentru parametri neimplicii.
11
12/13/2010
Cutarea se oprete n momentul n care se identific, n mod univoc, una dintre funcii. Dac n una din etape se identific mai mult de o soluie posibil, ambiguitatea este semnalat de compilator printr-un mesaj de eroare.
// apel funcia 1 // apel funcia 2 cu conversie nedegradant float -> double // apel funcia 1 cu conversie nedegradant char -> int // eroare la compilare datorat ambiguitii aprute n etapa a 3-a
void g(int a) { printf(\nApel functia 1 cu argumentul: %d, a); } void g( double a ) { printf(\nApel functia 2 cu argumentul: %d, a); }
12
12/13/2010
Funcii inline
Directiva de preprocesare #define ofer posibilitatea utilizrii macrodefiniiilor cu parametri. Scrierea acestora amintete de definiiile funciilor, dar identificatorii utilizai ca parametri nu sunt nsoii de precizarea tipului datelor. Dac fiierul surs (*.cpp) conine macrodefiniii, pentru fiecare apel al lor, preprocesorul insereaz n textul programului, n locul apelului, textul macrodefiniiei n care se substituie numele parametrilor formali cu cele ale parametrilor efectivi. Compilatorul preia apoi textul astfel modificat i apoi se efectueaz compilarea programului.
#include <stdio.h> #define fct( a , b ) a+b void main() { int i = 2, j = 5, k ; k = fct( i , j ); float r = 2.3, s = 5.2, t; t = fct( r , s ); printf(\nk=%d, k); printf(\nt=%f, t); }
Funcii inline
Avantajul folosirii macrodefiniiei fa de funcie este obinerea unui timp de execuie mai scurt, deoarece codul este inserat efectiv n locul apelului, eliminndu-se operaiile specifice apelului de funcii (transfer de parametri prin stiv, salvri etc.). Folosirea macrodefiniiilor implic ns o serie de dezavantaje: dimensiunea codului generat crete deoarece se insereaz codul corespunztor macrodefiniiei pentru fiecare apel; macrodefiniiile nu pot fi compilate separat; nu se fac verificri referitoare la tipul i numrul parametrilor; pot aprea probleme legate de transferul parametrilor, domeniul variabilelor, etc.
13
12/13/2010
Funcii inline
C++ ofer posibilitatea declarrii funciilor inline care mbin avantajele utilizrii macrodefiniiilor cu cele ale utilizrii funciilor. Funciile inline pstreaz toate proprietile funciilor privind verificarea validitii apelurilor, modul de transfer al parametrilor, domeniul declaraiilor locale. Spre deosebire de funciile ordinare, la fiecare apel al funciei, compilatorul insereaz codul obiect al funciei inline n codul programului, ceea ce are ca efect creterea vitezei de execuie, n schimb crete dimensiunea codului, deci funciile inline trebuie s fie foarte scurte, cu numr mic de instruciuni. Nu se poate compila separat o funcie inline i nu se pot folosi pointeri ctre asemenea funcii.
Funcii inline
#include <stdio.h> inline int max(int a, int b) { return (a>b) ? a : b; } void main() { int i, j; printf(\ni=); scanf(%d, &i); printf(\nj=); scanf(%d, &j); printf(\nmax = %d, max( i, j )); }
14