start     Articole     Despre mine     Contact     Cursul ABCprog    

Ce sunt functiile in C, ce parametri pot primi si care e diferenta dintre variabilele locale si cele globale

Junior programmer, software architect, project manager… Daca esti programator in C si ai una din functiile astea, am putea spune ca ai o… functie in C, nu-i asa? 🙂

Bineinteles ca nu despre astfel de functii vom vorbi aici — ci despre functii ca acelea despre care am discutat in Abecedarul de programare.

Aproape tot ce gasesti intr-un program scris in C sunt functii (sau (rar) variabile globale). Chiar si programul principal e o functie — functia numita main. Ai tot folosit-o pana acum (atat in forma int main() {… return 0;}, cat si in forma void main() {…}).

Hai sa incepem prin a vedea…

Cum definesti o functie in C

Stii bine ca atunci cand auzi de o functie in matematica trebuie sa te gandesti la legatura dintre elementele a doua multimi. Dar cand auzi de functie in programare trebuie sa te gandesti la functii dintr-o perspectiva operativa. Adica trebuie sa vezi functia ca pe o procedura de a obtine (prin operatii matematice aplicate succesiv) valoarea functiei pornind de la argumentul ei.

Sau — si mai generic — ar trebui sa vedem functia ca pe un mini-program (sau subprogram) care poate sa primeasca niste valori de intrare (sau argumente; sau parametri) si sa calculeze niste valori de iesire.

Asa ca pentru a defini o functie (intr-un program) trebuie sa ii dam un nume (ca sa o putem folosi (sau sa o putem “apela”, cum se zice)) si sa spunem ce argumente (sau parametri) are (si ce tip au fiecare), ce tip are valoarea calculata de functie si care e secventa de instructiuni necesare pentru a calcula valoarea de iesire din parametrii de intrare. Cu alte cuvinte, ceva de genul acesta:

    tip_valoare_calculata Nume_Functie (tip_param1 nume_param1, tip_param2 nume_param2, ...)
    {
        intructiuni...
        return valoare_calculata;
    }

Adica e asa cum ai vazut in Abecedar, doar ca in loc de function trebuie sa scrii tipul functiei (adica tipul valorii ce va fi returnata de catre functie), iar in lista ei de parametri trebuie sa specifici inainte de numele fiecarui parametru tipul lui.

Uite, ca exemplu, cum am face o functie ce returneaza maximul dintre doua valori (ambele de tip int):

    int Max(int a, int b)
    {
        if (a >= b)
            return a;
        else
            return b;
    }

Asa cum stii, instructiunea return opreste executia functiei in acel punct, asa ca functia Max as putea sa o scriu si asa:

    int Max(int a, int b)
    {
        if (a >= b)
            return a;
        return b;
    }

In programare, functiile pot sa nu returneze valori, ci sa fie doar subprograme al caror scop e sa execute o serie de instructiuni, urmarindu-se nu calcularea unei valori, ci obtinerea efectului executarii acelei secvente de instructiuni.

In cazul asta, tipul valorii returnate de functie va fi void. Uite un exemplu de astfel de functie care “deseneaza” un dreptunghi de dimensiuni specificate prin parametrii w (latimea) si h (inaltimea):

    void Dreptunghi(int w, int h)
    {
        int i, j;
        printf("+");
        for (j=1; j<=w; j++)
            printf("-");
        printf("+\n");
        for (i=1; i<=h; i++)
        {
            printf("|");
            for (j=1; j<=w; j++)
                printf(" ");
            printf("|\n");
        }
        printf("+");
        for (j=1; j<=w; j++)
            printf("-");
        printf("+\n");
    }

Functiile de tipul void pot si ele sa beneficieze de instructiunea return (care opreste executarea functiei in acel punct, revenind in locul din program in care acea functie a fost apelata), doar ca fara valoare dupa ea. Daca vrei sa opresti executia unei functii intr-un punct, scrii return; si gata.

Uite aici o functie care afiseaza pe rand (de la stanga la dreapta) elementele unui vector pana cand da peste primul numar negativ din vector:

    void AfiseazaPrimelePozitive(int[] v, int n)
    {
        int i;
        for (i=0; i<n; i++)
        {
             if (v[i] < 0)
                 return;
             printf("%d ", v[i]);
        }
    }

Vectorul v puteam sa il declar in lista de parametri a functiei si ca int v[], dar si ca int *v, caci in realitate functiei i se transmite un pointer — si anume adresa primul element din vector. Pentru a sti cate elemente sunt in vector ma folosesc de cel de-al doilea parametru, n.

Hai sa intram un pic mai in detaliu in problema transmiterii parametrilor catre o functie, si sa vedem…

Cum dai unei functii in C ca parametri variabile, si nu valori

Parametrii pe care ii primeste o functie sunt valori pe care functia doar le poate “citi”, fara sa poata interveni asupra sursei lor de provenienta. Sa luam un exemplu ilustrativ:

    #include <stdio.h>

    int Aduna1(int x)
    {
        x = x+1;
        return x;
    }
    
    void main()
    {
	int x = 1;
	Aduna1(x);
	printf("%d\n", x);
    }

Observam ca dupa apelul Aduna1(x) din functia main, valoarea variabilei x (din main) ramane tot 1, cu toate ca in functia Aduna1 ea a fost aparent marita cu 1.

(A se ramarca si faptul ca limbajul C imi permite sa apelez orice functie ca si cum ar returna tipul void — adica pot sa o apelez ca pe o simpla instructiune, fara sa ii folosesc valoarea returnata.)

Motivul pentru care in programul anterior functia Aduna1 nu modifica valoarea variabilei x prin apelul Aduna1(x) este acela ca la fel de bine puteam s-o apelez dandu-i ca parametru o constanta — adica, de exemplu, Aduna1(13).

(In acest al doilea caz, valoarea parametrului x va fi 13, iar dupa incrementare va ajunge 14, valoare pe care functia o va returna (dar care apoi nu e utilizata in programul principal).)

Cu alte cuvinte, apelul Aduna1(x) nu modifica valoarea variabilei x din functia main pentru ca functia Aduna1 primeste ca parametru o valoare, si nu o variabila.

Ar fi posibil, totusi, sa ii dau unei functii ca parametru nu o valoare, ci o variabila?

Teoretic, nu, dar practic, da. Caci pot transmite ca parametru unei functii o valoare ce reprezinta adresa unei variabile — adica pot avea ca parametru un pointer:

   int Aduna1(int* x)
    {
        (*x) = (*x)+1;
        return (*x);
    }

Asta inseamna ca aceasta noua functie va trebui s-o apelez in programul principal (adica in functia main) nu ca Aduna1(x), ci ca Aduna1(&x) — adica ii transmit nu valoarea variabilei x, ci adresa ei.

Deci daca dai ca parametru unei functii un vector, vei putea ca in interiorul functiei sa modifici valorile din vector?…

Sigur ca da! Ai vazut in lectia trecuta ca vectorul din C e, de fapt, un pointer (constant) catre primul sau element.

Ceea ce inseamna ca putem face o functie care sa adune ceva la o variabila si in felul urmator:

    void Aduna1(int x[])
    {
        x[0] = x[0]+1;
    }

Inainte de a incheia lectia asta, hai sa lamurim cum de nu se confunda parametrul x (din functia Aduna1) cu variabila x (din functia main).

Ce sunt variabilele locale si variabilele globale

Ai vazut deja ca in funtii se pot defini variabile. Ai tot folosit variabile in functia main pana acum, nu?

Dar si in functiile Dreptunghi si AfiseazaPrimelePozitive din lectia asta am definit variabile.

Astfel de variabile (definite in corpul unei functii) se numesc variabile locale. Adica toate variabilele pe care le-ai folosit pana acum au fost variabile locale. (Si parametrii functiilor au fost tot variable locale (pentru acea functie).)

OK, atunci ce sunt alea variabile globale?…

Sunt variabile pe care le definesti in afara functiei main si a oricarei alte functii. Le definesti, adica, in fisierul sursa acolo unde definesti functii (si mai sus de locul in care le vei folosi prima oara).

Sunt “globale” pentru ca le poti accesa (adica le poti citi si scrie) din toate functiile din program. Adica in orice functie poti folosi: variabilele ei locale, parametrii ei si variabilele globale.

Nu poti accesa (folosindu-i direct numele) din functia B apelata din functia A o variabila locala a functiei A.

Uite un exemplu (fara utilitate practica), ca sa intelegi ce zic:

    #include <stdio.h>

    int x = 1;
    
    void B(int n) {
        x = x+n;
    }       
    int A() {
        int x = 2;
        B(x); 
        return x;
    }  
 
    void main()
    {
        printf("%d ", A());
        printf("%d\n", x);
    }

Numele x apare in toate cele 3 functii, dar el se refera in functiile main si B la variabila globala x, in vreme ce in functia A se refera la variabila locala x.

Ce numere se vor afisa pe ecran dupa compilarea si executarea acestui progam? (Scrie, te rog, raspunsul intr-un comentariu, mai jos.)

Cam asta a fost lectia. Iti mai spun doar ca inainte de a putea folosi o functie trebuie sa o definesti (deasupra locului unde o folosesti prima oara). Sau macar sa o declari — adica sa ii scrii antetul ( tip Nume(parametri) ), urmat de ; .

Cum merg lectile de C pana aici? Te descurci? (Daca ai dificultati, e posibil sa fi sarit peste niste pasi…)

 

Alatura-te celor peste 8000 de oameni din armata noastra de creiere cu muschi si vei primi testul care iti va spune daca ai sau nu minte de programator.

In plus, vei fi mereu la curent cu tot ce pun la cale.

(Vei primi automat un email in care ti se va solicita acordul de prelucrare a datelor cu caracter personal.)

 

Cu drag,

Florin Bîrleanu





Loading Facebook Comments ...