Pe scurt
| Ce | Exemplu în C++ |
|---|---|
| Funcție care returnează o valoare | int suma(int n) { … return s; } |
| Subprogram care nu returnează nimic | void afiseaza(int v[], int n) { … } |
| Apelul | x = suma(52816); sau afiseaza(v, n); |
| Parametru transmis prin valoare | int n în antet: subprogramul lucrează pe o copie |
| Parametru transmis prin referință | int &mx în antet: subprogramul modifică variabila din apel |
| Tablou ca parametru | int v[]: elementele originale se pot modifica |
| Variabilă locală, globală | declarată în subprogram (există doar în timpul apelului), respectiv în afara oricărui subprogram |
| Subprograme predefinite | sqrt(x), abs(x), pow(a, b) din cmath; strlen(s) din cstring |
O funcție cu rezultat întoarce o valoare care poate fi folosită într-o expresie. Un subprogram void execută o acțiune fără să ofere o valoare utilizabilă într-o expresie. În C++, o procedură se reprezintă printr-o funcție cu tipul de rezultat void.
În detaliu
Antetul și corpul
Antetul spune trei lucruri: tipul rezultatului (int, long long, bool sau void dacă nu returnează nimic), numele și lista parametrilor formali, fiecare cu tipul lui. Corpul, între acolade, conține instrucțiunile. Instrucțiunea return expresie; încheie executarea și trimite valoarea înapoi în locul apelului. La Bacalaureat, cerința precizează exact numele, parametrii și ce returnează subprogramul, iar baremul punctează separat antetul.
Apelul și ordinea în program
La apel, valorile parametrilor efectivi se pun în parametrii formali, în ordine, iar executarea trece în corpul subprogramului; la final revine în instrucțiunea de unde a fost apelat. Subprogramul trebuie să fie definit (sau măcar declarat printr-un prototip, adică antetul urmat de ;) înaintea locului în care e apelat.
Prin valoare și prin referință
Un parametru transmis prin valoare este o variabilă nouă, care primește o copie a valorii din apel. Poți să îl modifici liniștit în subprogram: variabila din apel rămâne neschimbată. Un parametru transmis prin referință, scris cu &, este chiar variabila din apel, sub alt nume. Așa scrii subprograme care întorc mai multe rezultate, de exemplu cifra minimă și cifra maximă a unui număr. Ca parametru efectiv pentru o referință trebuie pusă o variabilă, nu o expresie: minmax(n, a, b), nu minmax(n, 1, 2).
Tablourile ca parametri
Un tablou nu se copiază la apel: subprogramul primește locul din memorie unde se află tabloul. De aceea int v[] în antet permite modificarea elementelor, fără &. Numărul de elemente se transmite separat, ca alt parametru. La matrice, antetul trebuie să precizeze numărul de coloane, de exemplu int a[][101].
Variabile locale și globale
O variabilă declarată în corpul unui subprogram este locală: există doar cât durează apelul, iar valoarea ei de început este nedefinită, dacă nu o inițializezi. O variabilă declarată în afara oricărui subprogram este globală: o văd toate subprogramele de după ea și pornește cu valoarea 0. Dacă o variabilă locală are același nume cu una globală, în acel subprogram se folosește cea locală. Când enunțul dă datele prin parametri, subprogramul lucrează numai cu ei; un subprogram care depinde de variabile globale e mai greu de refolosit.
Proiectarea modulară
O problemă mare se împarte în subprobleme, fiecare rezolvată de un subprogram scurt și verificat separat: unul citește datele, altul testează o proprietate, altul afișează. Programul principal devine o succesiune de apeluri, ușor de citit. Programa nouă de clasa a IX-a introduce subprogramele în Python, cu aceleași noțiuni: antet, corp, parametri, variabile locale și globale, returnarea rezultatelor.
Un exemplu minimal: funcție cu rezultat și funcție void
#include <iostream>
using namespace std;
int patrat(int x) { return x * x; }
void afiseazaPatrat(int x) { cout << patrat(x); }
int main() {
int y = patrat(3);
afiseazaPatrat(4);
cout << " " << y;
return 0;
}
În apelul patrat(3), parametrul formal x primește copia valorii 3; se calculează , iar return trimite 9 expresiei din main, care inițializează y. Apoi afiseazaPatrat(4) apelează la rândul ei patrat(4), primește 16 și îl scrie la ieșire; simpla evaluare a lui patrat(3) nu a afișat nimic. Ieșirea este 16 9. Expresia int z = patrat(2) + 1; este validă și dă 5, pe când afiseazaPatrat(2) + 1 nu este o expresie numerică, pentru că o procedură nu are valoare.
Exemplul 2 — mai multe ramuri cu return. Valoarea absolută a unui număr se poate calcula cu două return-uri:
int abs2(int x) {
if (x >= 0) return x;
return -x;
}
Pentru prima ramură întoarce 7 și funcția se încheie imediat; pentru condiția este falsă și se întoarce . Fiecare drum prin funcție ajunge la un return. Dacă una dintre ramuri ar lipsi, funcția ar putea ajunge la sfârșit fără valoare, iar rezultatul ar fi nedefinit.
Exemplul 3 — procedură cu mai multe rezultate. Pentru a afla și minimul, și maximul unui vector, o singură funcție nu poate întoarce două valori. Se folosește o procedură cu doi parametri prin referință:
void minmax(int v[], int n, int &mn, int &mx) {
mn = mx = v[0];
for (int i = 1; i < n; i++) {
if (v[i] < mn) mn = v[i];
if (v[i] > mx) mx = v[i];
}
}
Apelul minmax(arr, 4, mn, mx) pentru vectorul scrie în variabilele apelantului valorile mn = 1 și mx = 7. Procedura nu are return cu valoare; rezultatele ies prin parametri.
Mai multe funcții simple se pot combina: patrat(patrat(2)) are valoarea 16, pentru că întâi se evaluează apelul interior, 4, apoi cel exterior. O funcție poate apela și alte funcții definite înaintea ei, de pildă afiseazaPatrat, care apelează patrat.
Exemple suplimentare
Exemplul 4 — transmiterea prin valoare și prin referință. Cele două proceduri de mai jos au același corp, dar un antet diferit.
void schimbaV(int a, int b) { int t = a; a = b; b = t; }
void schimbaR(int &a, int &b) { int t = a; a = b; b = t; }
int main() {
int x = 3, y = 4;
schimbaV(x, y);
cout << x << ' ' << y << ' ';
schimbaR(x, y);
cout << x << ' ' << y;
return 0;
}
În schimbaV parametrii sunt copii ale lui x și y; interschimbarea modifică copiile, iar variabilele din main rămân 3 și 4. În schimbaR parametrii sunt alte nume pentru x și y, deci după apel x este 4 și y este 3. Se afișează 3 4 4 3.
Exemplul 5 — funcție cu rezultat logic. Funcția bool estePrim(int n) întoarce false pentru și altfel încearcă divizorii cât timp . Pentru ciclul găsește , care îl împarte exact, și întoarce false. Pentru încearcă numai și , nu găsește niciun divizor și întoarce true. Apelul se folosește direct într-o condiție: if (estePrim(13)) cout << "prim";.
Exemple rezolvate
Exemplul 1: o funcție care returnează o valoare
Scrie funcția suma, care primește un număr natural n și returnează suma cifrelor lui. Afișează suma cifrelor pentru 52816 și pentru 7.
#include <iostream>
using namespace std;
int suma(int n) {
int s = 0; // variabila locala
while (n > 0) {
s = s + n % 10;
n = n / 10; // se modifica doar copia lui n
}
return s;
}
int main() {
int x = 52816;
cout << suma(x) << " " << suma(7) << " " << x << "\n";
return 0;
}
Programul afișează:
22 7 52816
Parametrul n este transmis prin valoare, deci x rămâne 52816 după apel. În Python, programa nouă de clasa a IX-a scrie aceeași funcție astfel:
def suma(n):
s = 0
while n > 0:
s = s + n % 10
n = n // 10
return s
print(suma(52816), suma(7))
22 7
Exemplul 2: valoare sau referință
Ce afișează programul?
#include <iostream>
using namespace std;
void dublu(int x) {
x = 2 * x;
}
void dubluR(int &x) {
x = 2 * x;
}
int main() {
int a = 5, b = 5;
dublu(a);
dubluR(b);
cout << a << " " << b << "\n";
return 0;
}
dubluprimește o copie a lui a; copia devine 10, iar a rămâne 5.dubluRprimește chiar variabila b, care devine 10.
5 10
Exemplul 3: două rezultate prin referință
Scrie subprogramul minmax, care primește un număr natural nenul n și furnizează, prin parametrii mn și mx, cifra minimă și cifra maximă a lui n.
#include <iostream>
using namespace std;
void minmax(int n, int &mn, int &mx) {
mn = 9;
mx = 0;
while (n > 0) {
int c = n % 10;
if (c < mn) mn = c;
if (c > mx) mx = c;
n = n / 10;
}
}
int main() {
int a, b;
minmax(52816, a, b);
cout << a << " " << b << "\n";
return 0;
}
Programul afișează:
1 8
Exemplul 4: un tablou ca parametru
Scrie subprogramul inverseaza, care primește un vector v cu n elemente, pe pozițiile 1…n, și îi inversează ordinea elementelor.
#include <iostream>
using namespace std;
void inverseaza(int v[], int n) {
for (int i = 1; i <= n / 2; i++) {
int aux = v[i];
v[i] = v[n + 1 - i];
v[n + 1 - i] = aux;
}
}
int main() {
int v[] = {0, 4, 7, 1, 9, 3}; // pozitiile 1..5
inverseaza(v, 5);
for (int i = 1; i <= 5; i++)
cout << v[i] << " ";
cout << "\n";
return 0;
}
Programul afișează:
3 9 1 7 4
Vectorul din main s-a modificat, deși antetul nu are &.
Exemplul 5: nivel de examen, un număr construit din cifre
Subprogramul impare are un singur parametru, n, prin care primește un număr natural. Subprogramul returnează numărul format din cifrele impare ale lui n, în ordinea în care apar în n, sau −1 dacă n nu are nicio cifră impară. De exemplu, pentru 245731 returnează 5731, iar pentru 2468 returnează −1.
- Parcurgi cifrele de la dreapta la stânga. O cifră impară trebuie pusă în fața cifrelor păstrate deja, ca ordinea să rămână cea din n, deci o înmulțești cu puterea lui 10 corespunzătoare: r = r + c · p, apoi p = p · 10.
- Dacă nu ai găsit nicio cifră impară, returnezi −1. Ai putea testa și dacă r a rămas 0, pentru că nicio cifră impară nu este 0; variabila separată
gasitface însă condiția mai ușor de citit și tratează la fel și n = 0.
#include <iostream>
using namespace std;
int impare(int n) {
int r = 0, p = 1, gasit = 0;
while (n > 0) {
int c = n % 10;
if (c % 2 == 1) {
r = r + c * p;
p = p * 10;
gasit = 1;
}
n = n / 10;
}
if (gasit == 0)
return -1;
return r;
}
int main() {
cout << impare(245731) << " " << impare(2468) << " " << impare(102030) << "\n";
return 0;
}
Programul afișează:
5731 -1 13
Pentru 102030, cifrele impare sunt 1 și 3, în această ordine, iar zerourile, fiind pare, nu se păstrează.
Pentru admitere
Separă valoarea returnată de efectele secundare. cout << patrat(3) afișează 9 fiindcă apelantul folosește rezultatul; simplul apel patrat(3); nu afișează nimic. Într-o funcție cu rezultat, urmărește ramura care ajunge la return: instrucțiunile scrise după un return executat nu se mai execută. Când o funcție se apelează pe ea însăși sau pe alte funcții, evaluează apelurile de la cel mai interior spre exterior. Un compilator poate semnala ca avertisment un cod aflat după return, dar nu este eroare: instrucțiunea doar nu se execută. Dacă un fragment nu returnează valoare pe toate ramurile, rezultatul funcției în ramura lipsă este nedefinit și nu poate fi cerut într-un subiect.
Exemplu în formatul examenului. Ce se afișează în urma executării programului de mai jos?
#include <iostream>
using namespace std;
int f(int x) {
if (x > 5) return x - 5;
return x + 5;
cout << "A";
}
int main() {
cout << f(3) << f(f(3));
return 0;
}
- a)
85 - b)
8A3 - c)
83 - d)
88
Răspunsul corect este c). Pentru f(3), condiția este falsă, deci funcția întoarce ; instrucțiunea cout << "A" de după return nu se execută niciodată. Pentru f(f(3)) se evaluează întâi apelul interior, care dă 8, apoi f(8): condiția este adevărată, deci se întoarce . Se afișează 8 urmat de 3. Varianta b) presupune că "A" se afișează, iar varianta a) calculează greșit f(8).
Al doilea exemplu în formatul examenului. Ce se afișează în urma executării programului de mai jos?
#include <iostream>
using namespace std;
int g(int x) {
x = x + 2;
return x * 2;
}
int main() {
int a = 3;
cout << g(a) << ' ' << a;
return 0;
}
- a)
10 5 - b)
10 3 - c)
5 3 - d)
6 5
Răspunsul corect este b). Parametrul x este o copie a lui a: în g, x devine , iar funcția întoarce . Variabila a din main nu se modifică, deci rămâne 3. Se afișează 10 3. Varianta a) presupune că a se modifică, iar varianta c) uită înmulțirea cu 2.
Unde apare la examen
- Bacalaureatul, informatică, matematică-informatică: programa de examen cuprinde subprogramele predefinite și mecanismele de transfer prin parametri, apoi, la subprogramele definite de utilizator, declararea și apelul, parametrii formali și efectivi, transmiterea prin valoare și prin referință, variabilele globale și locale și proiectarea modulară (programa de examen, anexa 2 la OMECTS 4800/2010). La sesiunea din iunie–iulie 2026, primul exercițiu al Subiectului al III-lea (10 puncte) a cerut definiția completă a unui subprogram care construiește un număr din cifrele altui număr; baremul a punctat separat antetul, calculul, returnarea rezultatului și variabilele locale (subiectele și baremele Bac 2026). Formatul descris este cel din 2026; potrivit proiectului de ordin pentru Bacalaureatul 2027, programa rămâne aceeași.
- Programa școlară: pe programa veche, subprogramele și recursivitatea sunt la clasa a XI-a (programa de clasa a XI-a, OMECI 5099/2009); pe programa nouă, subprogramele încep în clasa a IX-a, în Python (OMEC 6930/2025, anexa 42).
Greșeli frecvente
- Greșit: o funcție
voidpoate fi folosită într-o expresie aritmetică.Corect: nu are valoare, deci apelul ei este doar o instrucțiune. - Greșit: instrucțiunile scrise după un
returnexecutat se execută și ele.Corect:returnîncheie imediat subprogramul. - Greșit: simplul apel
patrat(3);afișează rezultatul.Corect: valoarea returnată se afișează doar dacă apelantul o scrie. - Greșit: subprogramul modifică o variabilă din apel, deși parametrul nu are
&.Corect: fără&, rezultatul rămâne în copie și se pierde la ieșirea din subprogram (exemplul 2). - Greșit: subprogramul citește datele de la tastatură, deși enunțul le dă prin parametri.Corect: dacă enunțul spune „primește prin parametrul n”, subprogramul nu citește și nu afișează nimic, ci lucrează cu n și returnează rezultatul.
- Greșit:
returnpus în interiorul buclei, deși rezultatul depinde de toate elementele.Corect: unreturnoprește imediat subprogramul, deci îl pui după buclă. - Greșit:
int s;într-un subprogram, folosit ca sumă.Corect: o variabilă locală neinițializată poate conține orice valoare, deci scriiint s = 0;. - Greșit: o ramură a funcției se termină fără
return.Corect: într-o funcție care nu e de tipvoid, fiecare drum prin corp se încheie cureturn; altfel rezultatul e nedefinit. - Greșit: apelul
minmax(n, 1, 2)pentru un parametruint &x.Corect: pentru o referință, apelul primește o variabilă, nu o constantă sau o expresie. - Greșit:
return x;afișeazăx.Corect: întoarce valoarea apelantului. - Greșit: o funcție
voidpoate fi adunată ca un număr.Corect: nu produce o valoare pentru expresie.
Testează-te pe această lecție
Lecția o citești aici, fără cont. Testele pe lecții și capitole sunt în cont, cu grile originale Didaxis și explicația fiecăreia: gratuit 10 grile pe zi, fără limită cu Premium, 49 de lei pe lună pentru fiecare copil.
Înainte și după
Întrebări frecvente
Care este diferența dintre parametrii transmiși prin valoare și prin referință?
Ce sunt parametrii formali și parametrii efectivi?
Se modifică un tablou transmis unui subprogram?
Surse și referințe
Redactare proprie, conform programei:
- OMECI 5099/2009, anexa 5, Informatică, p. 4–5, clasa X intensiv; rocnee.eu
- OMECI 5099/2009, anexa 5, Informatică, p. 4–5, clasa XI; plan de încadrare: OMEC 7723/2024, anexa 2, tabelele 1–25, legislatie.just.ro; filiera tehnologică: OMEC 7724/2024, anexa 4, tabelul calificării, legislatie.just.ro
- UNSTPB, Regulament admitere licență 2026, Anexa II-1.2 p. Anx II-14 și Anexa XI-3 p. Anx XI-6–7 (PDF p. 64, 120–121); admitere.pub.ro
- OMECTS 4800/2010, anexa 2, Informatică, p. 3–4; edu.ro
Documente consultate
- UNSTPB, admitere 2026, anexa XI-3, p. Anx XI-6–7
- Programa școlară de informatică, clasa a XI-a (OMECI 5099/2009, anexa 5), CNCE; rocnee.eu
- Programa școlară de informatică, clasa a IX-a, matematică-informatică (OMEC 6930/2025, anexa 42); rocnee.eu
- Programa de bacalaureat la informatică, matematică-informatică (anexa 2 la OMECTS 4800/2010), Ministerul Educației, p. 4–5; edu.ro
- Subiectele și baremele Bacalaureatului 2026; subiecte2026.edu.ro
Desene: Redactare proprie (desen original), conform Programa școlară de informatică, clasa a XI-a (OMECI 5099/2009, anexa 5), CNCE; rocnee.eu
