Sunteți pe pagina 1din 7

VARIABILE

Compilatorul C alocă memorie variabilelor din program de dimensiune corespunzătoare tipului


fiecăreia.

Memoria se alocă în 2 moduri:

static, repartizată într-o zonă specială asociată programului;

dinamic, repartizată într-o zonă specială numită stivă (se comportă ca o listă LIFO).

În funcţie de modul cum se alocă memorie, vom distinge mai multe clase de variabile.

O primă clasă de variabile este aceea a variabilelor globale cărora li se alocă memorie pe toată
durata execuţiei programului şi ele pot fi utilizate în orice funcţie a programului. Altă clasă de
variabile este clasa variabilelor locale, aceste variabile au o utilizare locală la nivelul unei funcţii.

VARIABILE GLOBALE

O variabilă globală are o definiţie şi atâtea declaraţii de variabilă externă câte sunt necesare.

Definiţia unei variabile globale coincide sintactic cu o declaraţie obişnuită, dar care este scrisă în
afara oricărei funcţii a programului (fişierului sursă). Implicit, definiţia unei variabile globale
determină ca variabila respectivă să fie definită începând din punctul scrierii ei şi până la
sfârşitul fişierului sursă respectiv. De aceea se recomandă ca definiţiile variabilelor globale să fie
scrise la începutul fişierului sursă, pentru a fi accesate în orice funcţie a fişierului.

Pentru a utiliza variabilele globale şi în alte funcţii situate în alte fişiere sursă decât în cel în care
sunt definite, ele trebuie declarate ca externe în funcţiile respective.

O declaraţie de variabilă externă coincide cu o declaraţie obişnuită doar că începe cu cuvântul


cheie extern.

Exemplu:

fişierul în care sunt declarate ca variabile globale fişierul în care sunt folosite ca variabile externe

int i;

float f; void functie(. . .)

void main(void) { extern int i;

{ i = 10; extern double f;

......
f = 3.14; f = f*i;

......

}}

Variabilele i şi f sunt declarate în afara funcţiei main şi în afara oricărei funcţii, deci sunt
variabile globale. Ele pot fi folosite în toate funcţiile din fişierul sursă care conţine definiţiile lor.
Pentru a le utiliza în funcţii situate în alte fişiere sursă decât în cel în care sunt definite ele sunt
declarate ca externe. Deci variabilele i şi f sunt declarate ca externe în funcţia functie din al
doilea fişier sursă. Cele două fişiere sursă care pot fi scrise în momente şi de persoane diferite se
pot asambla într-un singur program cu ajutorul directivei de preprocesare include.

VARIABILE LOCALE
Variabilele locale nu sunt valabile în tot programul. Ele au o utilizare locală în două feluri:

ca şi variabile automatice (alocate pe stivă) la nivelul unei funcţii;

ca şi variabile statice (alocate în zona programului) la nivel de fişier (eventual şi la nivelul unei
funcţii).

Variabilele declarate în interiorul unei funcţii şi care nu sunt declarate ca externe sunt variabile
locale. Lor li se alocă memorie pe stivă la intrarea în funcţia în care sunt declarate. La ieşirea din
funcţie, stiva se reface la conţinutul dinaintea apelului şi variabilele locale pierd alocarea. Deci
ori de câte ori se apelează o funcţie, variabilele locale acesteia (denumite şi variabile automatice)
se alocă (primesc memorie) pe stivă şi la ieşirea din funcţie variabilele locale sunt şterse din
stivă.

Variabilele locale pot să nu fie alocate pe stivă, ci într-o zonă de memorie destinată acestui scop.
O astfel de variabilă locală se numeşte variabilă statică. O variabilă locală statică se declară
printr-o declaraţie obişnuită, precedată de cuvântul cheie static. O variabilă statică poate fi
declarată atât în corpul unei funcţii cât şi în afara oricărei funcţii. În cazul unei variabile statice
declarată în interiorul unei funcţii alocarea nu se face pe stivă ci într-o zonă de memorie destinată
acestui scop, aceasta fiind deosebirea esenţială faţă de variabilele automatice. În cazul în care o
variabilă statică este declarată în afara funcţiilor, ea este definită din punctul în care a fost
declarată şi până la sfârşitul fişierului sursă care conţine declaraţia ei. Spre deosebire de
variabilele globale, o variabilă statică nu poate fi declarată ca externă şi deci nu poate fi utilizată
în funcţiile din alte fişiere sursă diferite de cel în care a fost declarată.

Se recomandă ca tablourile mari să fie declarate statice, deoarece dacă sunt automatice pot
depăşi capacitatea stivei (care are implicit 4K octeţi).

Exemple:

Fişierul fisier1.c este un fişier sursă care conţine 2 variabile globale i şi d , o variabilă statică x şi
două funcţii f şi main. Funcţia main conţine variabila statică a iar funcţia f conţine variabila
statică b.

int i; // definiţia variabilei globale i

double d; // definiţia variabilei globale d


static int x; // definiţia variabilei statice x, locala fisierului fisier1.c

void main (void)

{ static char a; // definiţia variabilei statice a, locala funcţiei main

float c; // definiţia variabilei automatice c, locala funcţiei main

/* in acest moment se pot folosi variabilele i,d,x,a si c */

...

{ int p; // definiïia variabilei automatice p, locala funcïiei f

static float b; // definiïia variabilei statice b, locala funcïiei f

/* in acest moment se pot folosi variabilele i,d,x, p si b */

...

Variabilele a şi c fiind locale funcţiei main nu pot fi utilizate în funcţia f. Analog, variabilele p şi
b sunt locale în funcţia f, nu pot fi utilizate în funcţia main.

Fişierul fisier2.c conţine funcţiile f1 şi f2 care intră în componenţa aceluiaşi program ca şi


funcţiile main şi f din fişierul fisier1.c

static unsigned t; // definitia variabilei statice t, locala fisierului fisier2.c

void f1(...)

{ extern int i; // declaratie externa pentru i

extern double d; // declaratie externa pentru d

static int k; // definitia variabilei statice k, locala functiei f1

/* in acest moment se pot folosi varibilele i,d, k si t */

...

}
void f2(...)

{ extern int i; // declaratie externa pentru i

static double s; // definitia variabilei statice s, locala functiei f2

/* se pot folosi variabilele i, s si t */

...

Variabila statică x definită în fişierul fisier1.c nu poate fi utilizată în fişierul fisier2.c. De


asemenea, variabila statică t nu poate fi utilizată în fişierul fisier1.c. Variabila globală d nu poate
fi utilizată în funcţia f2, ea nefiind declarată ca şi externă.

Observaţii:

1 Variabilele globale constituie un mijloc simplu de interfaţă între funcţiile unui program. Se
recomandă a fi folosite când dorim transferuri de valori între două sau mai multe funcţii în aşa
fel încât modificările realizate de o funcţie să fie accesibile pentru toate funcţiile programului.
Nu trebuie să se facă abuz în utilizarea variabilelor globale deoarece constituie şi o sursă
potenţială de erori, pentru că accesul unui mare număr de funcţii la anumite date globale conduce
deseori la modificări nedorite şi greu evidenţiabile.

2 Funcţiile sunt considerate cu atributul implicit extern. Dacă într-un program există mai multe
fişiere sursă atunci o funcţie poate fi apelată oriunde, bine înţeles respectând convenţia definirii
ei sau a prototipului ei înainte de a fi folosită. Putem să limităm definind funcţiile cu atributul
static precedând antetul funcţiei prin cuvântul cheie static. Astfel funcţia respectivă devine locală
şi deci apelabilă doar în fişierul în care este definită.

VARIABILE REGISTRU

Limbajul C oferă posibilitatea de a aloca anumite variabile în regiştri microprocesorului.


Deoarece regiştri constituie un tip de memorie ultrarapidă în anumite cazuri se poate economisi
atât timp de execuţie cât şi memorie. Se pot aloca în regiştri numai parametrii funcţiilor şi
variabilele automatice de tip int, char şi de tip pointer. O variabilă registru se declară în mod
obişnuit, precedând declaraţia ei prin cuvântul rezervat register.

Alocarea într-un registru a unei variabile se face numai dacă există un registru disponibil. În caz
contrar, variabila registru se alocă pe stivă exact ca o variabilă automatică. Alocarea se face în
ordinea declarării variabilelor registru.

Exemplu:
void f (register int i)

{ register char c;

register int j;

...

Mai întâi se alocă parametrul i într-un registru, apoi se alocă c şi j în alţi doi regiştri.

Se recomandă alocarea în regiştri a variabilelor care au o utilizare mare, de exemplu a indicilor


de tablouri.

INIŢIALIZARE
Variabilelor li se pot atribui valori iniţiale. Pentru variabilele globale valorile iniţiale se atribuie
prin definiţiile lor, iar în cazul celorlalte variabile se pot atribui valori prin declaraţiile lor. Pentru
că de multe ori am folosit cuvintele definiţia variabilelor sau declaraţiile varibilelor precizăm că
ele au înţeles distinct în anumite contexte. O variabilă globală se defineşte o singură dată şi se
poate declara ori de câte ori e necesară utilizarea ei în alte fişiere (evident declarată externă). În
cazul celorlalte tipuri de variabile definiţiile şi declaraţiile coincid. Totodată definiţia şi
declaraţia (prototipul) unei funcţii nu coincid.

O variabilă simplă se poate iniţializa printr-o declaraţie de forma:

tip nume=expresie;

Variabilelor globale şi statice li se atribuie valori iniţiale la lansarea programului. Expresia


utilizată în cazul acestor variabile trebuie să fie o expresie constantă care să poată fi evaluată de
compilator la întâlnirea ei. Aceasta, deoarece variabilele globale şi statice se iniţializează prin
valori definite la compilare.

Variabilele automatice se iniţializează la execuţie, de fiecare dată când se activează funcţia în


care sunt declarate. Din această cauză, nu mai este necesar ca expresia să fie o expresie
constantă. Totuşi, la întâlnirea ei, trebuie să fie definiţi operanzii expresiei de iniţializare.

Exemplu:

void f(int n)

{ int i=10;

int k=i+n;

...
}

La întâlnirea expresiei i+n sunt deja definiţi ambii operanzi:

i a fost în prealabil iniţializat cu valoarea 10;

n are o valoare care e transferată la apel.

Variabilele globale şi statice neiniţializate au implicit valoarea egală cu zero, iar varibilele
automatice neiniţializate au o valoare iniţială imprevizibilă.

Tablourile se pot iniţializa printr-o listă de expresii incluse între acolade. Astfel un tablou
unidimensional se poate iniţializa folosind următorul format:

tip nume[n] = { exp1, exp2, . . . expn }

La iniţializarea tablourilor se pot utiliza numai expresii constante. Numărul expresiilor poate fi
mai mic decât numărul elementelor tabloului. Elementele neiniţializate au valoarea zero în cazul
tablourilor globale şi statice. Dacă se iniţializează fiecare element al tabloului atunci numărul n
al elementelor acestuia nu mai este obligatoriu în declaraţia tabloului respectiv. Deci se poate
scrie astfel:

tip nume[ ] = { exp1, exp2, . . . expn};

Numărul elementelor tabloului se consideră că este egal cu cel al expresiilor care realizează
iniţializarea lor.

Pentru un tablou bidimensional vom folosi următoarea structură:

tip nume [n][m] = { {exp11, exp12, . . . exp1m}, // pentru linia întâi

{exp21, exp22, . . . exp2m}, // pentru linia a doua

...

{expn1, expn2, . . . expnm}, // pentru ultima linie

};

Numărul expresiilor poate fi mai mic decât m în oricare din acoladele corespunzătoare celor n
linii ale tabloului bidimensional. În acest caz se poate omite doar numărul n (al liniilor
tablourilor), m fiind obligatoriu. Formatul de iniţializare a tablourilor bidimensionale se extinde
imediat pentru tablouri cu mai multe dimensiuni.

Tablourile de tip caracter pot fi iniţializate folosind un format mai simplu decât cel indicat
anterior. Astfel. un tablou de tip caracter se poate iniţializa printr-o declaraţie de forma:

char sir[n] = şir_de_caractere;

Evident, marginea superioară n poate fi omisă şi în acest caz. Totodată compilatorul pune
automat caracterul NUL după ultimul caracter al şirului utilizat în iniţializare.
Exemple:

1) int itab[] = {1,2,3,4,5} // tabloul de tip intreg are 5 elemente itab[0] = 1,. . . itab[4] = 5

2) int m[3][3] = {{-1,0,1},{-1},{0,1}}; // tabloul are 3 linii si 3 coloane.

Elementele primei linii sunt iniţializate astfel:

m[0][0] = –1;

m[0][1] = 0;

m[0][2] = 1;

În linia a doua se iniţializează numai m[1][0] = -1; Dacă tabloul ar fi declarat global sau static
atunci m[1][1] şi m[1][2] ar avea valoarea zero. Altfel ele au o valoare imprevizibilă.

Elementele ultimei linii se iniţializează astfel:

m[2][0] = 0;

m[2][1] = 1;

declaraţiile de mai jos sunt identice:

char sir [ ] = {‘L’,’I’,’M’,’B’,’A’,’J’,’U’,’L’, ‘ ‘,‘C’};

char sir [ ] = {“LIMBAJUL C”};

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