De ce contează?
Imaginează-ți avizierul de la intrarea unui bloc: oricine locuiește acolo îl poate citi și oricine poate scrie pe el. Un anunț pus dimineața rămâne acolo toată ziua, iar dacă doi vecini scriu peste el, ultimul șterge ce a scris primul. O variabilă globală este exact acest avizier al programului: o vede orice funcție, durează cât tot programul, dar dacă mai multe funcții scriu pe ea, e greu de spus cine a stricat ce.
Ce este
O variabilă globală este o variabilă declarată în afara oricărei funcții (de obicei sus, sub #include-uri, înainte de main). Spre deosebire de o variabilă locală, care există doar înăuntrul funcției unde a fost declarată, variabila globală are două proprietăți care o deosebesc:
- Domeniu global — este vizibilă în orice funcție din fișier. Nu trebuie să o transmiți ca parametru: orice funcție o poate citi și modifica direct, după nume.
- Durată cât tot programul — se creează o singură dată, la pornirea programului, și trăiește până la final. Valoarea ei nu se pierde între apeluri de funcții, așa cum se pierde cea a unei variabile locale când funcția se termină.
Mai e o diferență subtilă, dar importantă la concurs: variabilele globale sunt inițializate automat cu 0 (vectorii globali — toți cu 0, bool cu false). Variabilele locale NU primesc această garanție — o variabilă locală neinițializată conține gunoi. De aceea un int v[100000]; global e gata umplut cu zerouri, iar același vector declarat local în main nu este.
Cum arată
Un tipar tipic de concurs: citești n și un vector v, apoi le folosești din mai multe funcții. Dacă n și v sunt globale, nu mai trebuie să le cari ca parametri prin fiecare apel.
int n; // global: vizibil peste tot, pornit cu 0
int v[100]; // global: toate cele 100 de celule pornite cu 0Cheia e cine poate vedea avizierul. Cele trei funcții de mai jos — citeste(), suma() și main() — se uită toate la aceiași n și v globali. Nu există copii separate: este un singur exemplar partajat, declarat o dată sus.
citeste() | suma() | main() |
f1 | f2 | f3 |
Hai să urmărim ce este în vector după ce citeste() îl umple cu {5, 3, 8} (pentru n = 3). Restul celulelor rămân 0, fiindcă un vector global pornește cu zerouri:
5 | 3 | 8 | 0 | 0 |
0 | 1 | 2 | 3 | 4 |
n=3 |
Când suma() se execută apoi, ea nu primește nimic ca parametru — pur și simplu citește n și v direct de pe avizier și adună 5 + 3 + 8 = 16.
Implementare C++
Program complet: o funcție umple vectorul global, altă funcție îl citește. Observă că niciuna nu primește n sau v ca parametru — le văd fiindcă sunt globale.
#include <iostream>
using namespace std;
int n; // global: vizibil in orice functie
int v[100]; // global: pornit automat cu 0
// umple vectorul global; nu primeste nimic, scrie direct in v
void citeste() {
cin >> n;
for (int i = 0; i < n; i++)
cin >> v[i];
}
// citeste vectorul global si returneaza suma; nu primeste nimic
long long suma() {
long long s = 0; // local: trebuie initializat noi
for (int i = 0; i < n; i++)
s += v[i];
return s;
}
int main() {
citeste(); // pune date in n si v (globale)
cout << suma() << endl; // foloseste aceleasi n si v
return 0;
}
// Intrare: 3 apoi 5 3 8
// Iesire: 16Pentru intrarea 3 și apoi 5 3 8, programul afișează 16. Datele puse de citeste() în v rămân acolo când rulează suma() — exact pentru că v este global și nu dispare între apeluri.
Variabilele globale par comode, dar întind patru capcane:
- Stare partajată ascunsă. Dacă o funcție modifică
vși uiți, alta citește valoarea greșită — și nimic din semnătura funcției nu te avertizează. Bug-ul vine „de nicăieri", fiindcă legătura dintre funcții e invizibilă. - Coliziune de nume. Dacă declari un
int n;local într-o funcție, el ascunde globalulnîn interiorul ei. Crezi că modifici globalul, dar scrii în local — răspuns greșit, fără eroare de compilare. - Te bazezi pe zeroul implicit unde nu există. Globalele pornesc cu
0, dar variabilele locale nu.long long s;local fărăs = 0adună peste gunoi. Inițializează mereu localele tu. - Abuzul face codul de necitit. Dacă totul e global, nu mai poți spune ce funcție depinde de ce; depanarea devine un coșmar.
La concurs un n și un vector global sunt acceptabile — simplifică și sunt gata cu zerouri. Dar nu transforma fiecare variabilă în globală: ține globale doar datele cu adevărat comune (n, vectorul de intrare), iar restul lasă-le locale.