Sunteți pe pagina 1din 14

12/13/2010

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>

Tipul parametrului poate fi orice tip valid de date.

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

Declaraii de funcii. Prototipuri.


Apelul unei funcii nu se poate face nainte de definirea ei. Sunt situaii n care nu este posibil acest lucru (n cazul funciilor care se apeleaz unele pe altele, sau al funciilor definite n alte fiiere surs). Pentru a oferi compilatorului posibilitatea de a verifica corectitudinea apelului unei funcii se pot folosi declaraii fr definire, numite prototipuri. Sintaxa general a unui prototip este : <tip> nume_functie (<lista_parametri>); n declaraia funciei este suficient ca n lista_parametri s se specifice tipurile parametrilor, fr identificatorii lor. Dac ns se specific identificatorii, acetia trebuie s fie identici cu cei folosii n antetul definiiei funciei. Prototipul funciei trebuie s fie plasat nainte de orice apel al funciei.

Declaraii de funcii. Prototipuri.

12/13/2010

Declaraii de funcii. Prototipuri.

Parametri formali a = aria(raza); l = lungime(raza); a = aria(5); l = lungime(2 * raza);

Parametri efectivi

float aria(float); float lungime(float);

Transferul datelor prin parametri


Pe parcursul execuiei programelor, este necesar s se realizeze schimburi de date ntre funcii. Acest lucru se poate realiza prin: parametrii funciilor valoarea returnata de funcie O funcie C/C++ nu poate returna dect un obiect Este important modul n care se face transferul acestor informaii, astfel nct s nu se ocupe memorie n mod inutil, viteza de execuie a programului s fie ct mai mare i s se asigure protecia datelor care nu trebuie modificate n mod necontrolat. Transferul datelor ntre funcii se poate face n trei moduri: transfer prin valoare; transfer prin pointeri; transfer prin referine.

12/13/2010

Transfer prin valoare. Conversii de tip.


La apelul unei funcii, se aloc pe stiv parametrii formali ai funciei. Parametrii formali sunt variabile ce au ca domeniu funcia creia le aparin, ei disprnd dup terminarea funciei. Dup alocarea lor n memorie, ei sunt iniializai cu valoarea parametrilor efectivi. Din parametrii efectivi se copiaz valorile, ei nu sunt folosii n interiorul funciei, deci nu sunt afectai de nici o operaie care se efectueaz asupra parametrilor formali, ceea ce poate constitui o protecie util. Transferul de valoare este nsoit de eventuale conversii de tip realizate de compilator, implicite sau explicite dac se folosete operatorul cast. Conversia se realizeaz de la tipul parametrului efectiv ctre tipul parametrului formal.

Transfer prin adres

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

Transfer prin referin

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 parametri

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);

Transfer prin adres

Transfer prin referin

void schimba(int *a, int *b) { int temp ; temp = *a; *a = *b; *b = temp; }

void schimba(int &a, int &b) { int temp ; temp = a; a = b; b = temp; }

int p, q; schimba(&p, &q);

int p, q; schimba(p, q);

12/13/2010

Transfer prin parametri

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.

Transfer prin parametri


#include <stdio.h> #include <conio.h> void modific_valori(const float*a, const int n) { for (int i=0; i<n ; i++) a[i]= 2*a[i]; // eroare, se ncearc modificarea unui obiect const } void afisare(const float*a, const int n) { printf("\n"); for (int i=0; i<n ; i++) printf("%8.2f", a[i]); } void main(void) { float arr[5] = {1.1, 2.2, 3.3, 4.4, 5.5}; f(arr , 5); afisare(arr , 5); }

12/13/2010

Transfer prin valoare. Conversii de tip.


Instruciunea return determin ncheierea execuiei unei funcii i revenirea n funcia apelant. return(expresie); Valoarea expresiei reprezint rezultatul ntors de funcie, deci trebuie s fie compatibil cu tipul indicat n prototip i definiie. Dac tipul funciei este void, instruciunea return este necesar doar dac se dorete revenirea din funcie nainte de execuia ntregii secvene de instruciuni care alctuiete funcia. Transferul rezultatului se poate face utiliznd toate cele trei metode: prin valoare, pointer sau referin. n cazul transferului prin pointer sau referin, obiectul a crui adres se ntoarce nu trebuie s fie un obiect automatic, deoarece acesta dispare odat cu terminarea execuiei funciei.

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

// p_f, pointer de funcie

// se atribuie adresa funciei fct pointerului p_f // se apeleaz funcia fct prin pointerul p_f

Funcii cu parametri cu valori implicite


C++ ofer posibilitatea declarrii funciilor cu valori implicite ale parametrilor. La apelarea unor astfel de funcii, se poate omite specificarea parametrilor efectivi pentru acei parametri formali care au declarate valori implicite, transferndu-se automat valorile respective.
#include <stdio.h> void f(int, int = 20); // prototip de funcie cu un parametru // normal i un parametru implicit

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

Funcii cu parametri cu valori implicite

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.

Supradefinirea (suprancrcarea) funciilor


Limbajul C++ ofer posibilitatea de a atribui unui simbol mai multe semnificaii care pot fi distinse n context. Se poate folosi supradefinirea funciilor atunci cnd anumite activiti trebuie efectuate pentru liste de parametri diferite, att ca tipuri ct i ca numr. Selectarea funciei (codului executabil care se va executa) se face n urma comparrii tipurilor parametrilor efectivi cu tipurile parametrilor formali din diferitele declaraii ale funciilor cu acelai nume. Selecia se realizeaz n mai multe etape de cutare a corespondenei optime, uneori implicnd conversii de tip. 1. iniial se caut coincidena tipului parametrului efectiv cu cel formal; 2. n caz de eec al primei etape, se iniiaz o cutare nsoit de conversii implicite nedegradante; 3. n caz de eec al etapei a doua, se reia cutarea folosind conversii standard; 4. se admite utilizarea unei singure conversii de tip definit de utilizator.

11

12/13/2010

Supradefinirea (suprancrcarea) funciilor


Selecia se realizeaz n mai multe etape de cutare a corespondenei optime, uneori implicnd conversii de tip: 1. iniial se caut coincidena tipului parametrului efectiv cu cel formal; 2. n caz de eec al primei etape, se iniiaz o cutare nsoit de conversii implicite nedegradante; 3. n caz de eec al etapei a doua, se reia cutarea folosind conversii standard; 4. se admite utilizarea unei singure conversii de tip definit de utilizator.

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.

Supradefinirea (suprancrcarea) funciilor


#include <stdio.h> void g(int); void g(double); void main() { int i = 5; float r = 2.5; char c = a; long l = 10000; g( i ); g( r ); g( c ); g( l ); } // funcia 1 // funcia 2

// 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

S-ar putea să vă placă și