Variabile.
1. Variabile externe (globale) si variabile interne (locale).
Un program C este un ansamblu de obiecte externe: variabile si functii.
O variabila externa este o variabila definita in afara oricarei functii, fiind astfel accesibila din orice functie. Am vazut ca functiile pot comunica intre ele prin variabile externe sau globale.Orice functie poate accesa o variabila externa, referindu-se la aceasta prin numele ei, daca acest nume a fost declarat.
Prin urmare, variabilele externe au ca domeniu (sunt vazute si pot fi accesate din) intregul fisier sursa in care sunt definite.
Durata de viata a unei variabile externe (adica intervalul in care memoria este alocata) coincide cu durata in care programul C este activ. Variabilele externe sunt permanente: ele retin valori intre apelurile diferitelor functii.
Spre deosebire de variabilele externe, variabilele interne (numite si automatice sau locale) au un domeniu mult mai restrans - ele sunt cunoscute numai in interiorul functiei in care sunt definite.
Durata de viata a variabilelor interne este mult mai scurta ca a variabilelor externe – alocarea de memorie se face la intrarea in functie, pentru ca la parasirea functiei, memoria ocupata de variabila sa fie eliberata.
Intre ele, functiile sunt intotdeauna externe, pentru ca nu pot fi definite in interiorul altor functii (ca in Pascal!).
2. Domenii de vizibilitate ale variabilelor.
Functiile si variabilele externe din care este alcatuit programul nu trebuie sa fie compilate in acelasi timp; textul programului sursa poate fi separat in mai multe fisiere.
Domeniul unui nume reprezinta partea din program in care numele poate fi folosit.
Astfel pentru o variabila locala, definita la inceputul unei functii, domeniul il reprezinta acea functie. Variabilele locale cu acelasi nume din functii diferite sunt entitati diferite. Acelasi lucru este valabil si pentru parametrii formali ai functiilor, care sunt de fapt variabile locale.
Domeniul unei variabile externe, ca si a unei functii se intinde din punctul in care a fost declarata si pana la sfarsitul fisierului sursa.
O variabila externa poate fi referita si dintr-un alt fisier sursa al programului, daca este declarata in acest fisier cu atributul extern.
O asemenea declaratie anunta proprietatile variabilei (tipul), fara a aloca memorie pentru variabila.
De exemplu: extern int x;
Alocarea de memorie se face o singura data si anume in fisierul sursa in care variabila externa este definita. Tot in acel loc se face si initializarea variabilei externe.
Intr-o functie sunt vizibili:
parametrii formali
variabilele locale
variabilele globale locale modulului care declara functia ( variabilele declarate in afara functiei in aceeasi unitate de compilare;
variabilele globale exportate de alte module si importate de modulul care declara functia.
Orice definitie este si o declaratie, dar reciproca nu este adevarata. Astfel prototipul unei functii este o declaratie.
3. Clase de memorare.
Orice variabila are 4 atribute:
1. Clasa de memorare - reprezinta locul in care este memorata variabila:
intr-un segment de date
intr-un registru
in stiva
in heap
2. Vizibilitatea - reprezinta liniile textului sursa din care variabila poate fi accesata
la nivel de bloc - variabila este cunoscuta intr-un bloc, din momentul declararii pana la sfarsitul blocului
la nivel de fisier - variabila este cunoscuta intr-un fisier.
3. Durata de viata - reprezinta timpul in care variabila are alocat spatiu in memoria interna.
durata statica - variabila are alocat spatiu pe tot timpul executiei programului. Variabilele statice sunt memorate intr-un segment de date si sunt in mod automat initializate cu 0.
durata locala - variabila are alocat spatiu cat timp se executa instructiunile unui bloc. Alocarea de spatiu se face in stiva sau intr-un registru.
durata dinamica - variabila este alocata si dezalocata in timpul executiei programului prin functii speciale. Alocarea de spatiu se face in heap.
4. Tipul variabilei - determina numarul de octeti rezervati pentru variabila.
Atributele unei variabile se stabilesc:
implicit - in locul unde se face declaratia
explicit - prin anumiti calificatori.
Variabilele pot clasificate in:
variabile globale
variabile locale.
Variabilele globale:
se definesc in afara corpurilor functiilor
li se rezerva spatiu intr-un segment de date, inainte de executia programului
au durata de viata statica
sunt initializate implicit
au vizibilitate la nivel de fisier
vizibilitatea lor poate fi extinsa la nivel de program
O variabila globala poate fi accesata dintr-un fisier care nu contine definitia variabilei, dar trebuie sa contina o declaratie a variabilei, care contine numele variabilei precedat de specificatorul extern.
/* FISIER1.C */
int x=5; /* aici se defineste variabila x */
void F(); /* prototipul functiei F, definita in FISIER2.C */
void main()
/* FISIER2.C */
#include <stdio.h>
extern a; /* declararea variabilei definite in alt fisier */
void F() /* aici se defineste functia F */
Daca declaratia unei variabile este facuta inafara corpului functiei, ea este vizibila din punctul declaratiei pana la sfarsitul fisierului.
Daca declaratia variabilei se face in corpul unei functii, ea este vizibila din locul declararii, pana la sfarsitul blocului.
3.1. Variabile si functii statice.
Declararea unei variabile externe sau functii cu atributul static limiteaza domeniul obiectului la fisierul sursa compilat. Folosirea cuvantului extern nu asigura, in acest caz accesul din alt fisier la obiectul declarat static.
Variabilele interne pot fi si ele declarate statice. Prin aceasta ele vor ramane alocate si dupa iesirea din functie, asigurand memorarea de valori intre apeluri ale functiei. Variabilele interne statice :
au durata de viata din momentul definitiei pana la sfarsitul executiei programului
sunt memorate intr-un segment de date
sunt initializate automat
definitia lor incepe cu cuvantul static
#include <stdio.h>
static double a;
void main()
Variabila a este locala (fara specificatorul static ar fi fost globala). a este initializata la 0, astfel ca in primul apel se va afisa 1; urmatorul apel preia valoarea existenta (1), pe care o incrementeaza, deci afiseaza 2, s.a.m.d. Vizibilitatea este la nivelul fisierului (modulului) si nu se poate extinde la nivelul programului.
#include <stdio.h>
void increm(void)
void main(void)
Exemplul 14: Definiti o functie pentru generarea de numere intregi aleatoare.
xn+1 = (a*xn + b) % c,
in care x0 poarta numele de samanta (seed) generatorului. a, b si x0 sunt numere prime, care asigura o distributie aleatoare a numerelor in secventa . c da domeniul in care se genereaza numerele aleatoare si se alege, de obicei, tot un numar prim. Functia generator de numere aleatoare calculeaza cu relatia de mai sus pe xn+1 si-l intoarce ca rezultat. Valoarea xn trebuie sa provina din apelul precedent al functiei, asa ca va fi declarata ca variabila statica, initializata cu valoarea samantei x0. Initializarea va fi facuta numai la primul apel al functiei, la fiecare din apelurile urmatoare se preia valoarea ramasa din apelul precedent. Se remarca faptul ca se genereaza intotdeauna aceeasi secventa de numere aleatoare! Pentru a genera de fiecare data o alta secventa aleatoare, samanta ar trebui generata aleator.
Exista doua functii de biblioteca:
int rand(void); - care intoarce (daca este folosita singura), o aceeasi secventa de numere pseudoaleatoare
in domeniul 0 : RAND_MAX
void srand(unsigned s); - care stabileste valoarea samantei (x0)
unsigned aleator(unsigned long c)
3.2. Variabile registri.
Pentru variabilele folosite in mod frecvent, pentru cresterea eficientei programului, se doreste ca alocarea sa se faca in registrii masinii. In acest scop variabilele se declara cu atributul register.
De exemplu:
register int a;
register char c;
Pot fi declarate ca variabile registri numai variabilele automatice. Numai putine tipuri de variabile (care ocupa putina memorie) permit declararea ca variabile registri (de exemplu tipurile char si int dar nu double!).
Intrucat numarul de registri masina este limitat, declararea prea multor variabile de acest tip determina ca, de la un anumit moment sa se ignore aceasta declaratie, si anume, dupa alocarea registrilor disponibili
Variabilelor alocate in registri nu poate sa le fie aplicat operatorul de adresare.
Variabile definite in interiorul blocurilor.
O variabila definita in interiorul unei instructiuni compuse ascunde o variabila cu acelasi nume definita intr-un bloc exterior si dureaza pana la terminarea blocului.
O variabila definita si initializata intr-un bloc, va fi reinitializata la fiecare intrare in acel bloc.
O variabila statica, definita si initializata intr-un bloc, va fi initializata o singura data, la prima intrare in acel bloc.
3.3. Initializari.
In absenta unei initializari explicite, variabilele externe si cele statice sunt initializate la 0, in timp ce variabilele interne si registri raman neinitializate.
In cazul unei initializari
explicite, initializatorul unei variabile externe sau statice poate fi o
expresie
4. Probleme propuse.
1. Numerele naturale pot fi clasificate in: deficiente, perfecte sau abundente, dupa cum suma divizorilor este mai mica, egala sau mai mare decat valoarea numarului. Astfel: n=12 este abundent deoarece are suma divizorilor: sd = 1+2+3+4+6 = 16 > 12, n=6 este perfect: sd = 1+2+3 = 6, iar n=14 este deficient deoarece sd = 1+2+7 < 14.
Definiti o functie avand ca parametru un numar intreg n, functie care intoarce ca rezultat –1, 0 sau 1 dupa cum numarul este deficient, perfect sau abundent.
Scrieti o functie main care citeste doua valori intregi x si y si clasifica toate numerele naturale cuprinse intre x si y afisand dupa fiecare numar tipul acestuia, adica deficient, perfect sau abundent.
2. O pereche de numere naturale a si b se numesc numere prietene, daca suma divizorilor unuia dintre numere este egala cu celalalt numar. De exemplu 220 si 284 sunt numere prietene deoarece:
a) Scrieti o functie avand ca parametri un numar natural, care intoarce suma divizorilor numarului.
b) Scrieti o functie avand ca parametri doua numere naturale, care intoarce 1 sau 0, dupa cum cele doua numere sunt sau nu prietene.
c) Scrieti o functie main(), care in intervalul x, y dat gaseste toate perechile de numere prietene si le afiseaza.
3. Sa se rezolve ecuatia f(x)=0, prin metoda tangentei, pornind cu un x(0) dat, si calculand
x(k+1)=x(k) -f(x(k))/f'(x((k)) cu o precizie data eps, care se atinge cand |x(k+1) - x(k)| < eps). Functiile f(x) si f’(x) sunt date de programator.
4. Se considera functia f(x) = ln (1 + x2). Sa se scrie un program care tabeleaza functia pe n intervale, fiecare interval fiind precizat prin capetele a si b si pasul de afisare h.
5. Sa se scrie toate descompunerile unui numar par ca o suma de doua numere prime. Se va utiliza o functie care stabileste daca un numar este sau nu prim.
6.Sa se scrie in C:
a) Un subprogram functie pentru calculul valorii unei functii f(x) pentru o valoare data x, definita astfel:
b) O functie pentru calculul integralei definite:
prin metoda trapezelor, cu n pasi egali, pe intervalul [a,b], dupa formula
unde h=(b-a)/n
c) Un program care calculeaza integrala unei functii definite la punctul a), folosind functia b), pe un interval dat [p,q], cu precizia epsilon (se repeta calculul integralei pentru n=10, 20, pasi, pana cand diferenta dintre doua integrale succesive devine mai mica decat epsilon
7.Pentru un numar dat N sa se afiseze toti factorii primi ai acestuia si ordinul lor de multiplicitate.Se va utiliza o functie care extrage dintr-un numar un factor prim.
8. Utilizand o functie pentru calculul celui mai mare divizor comun a doua numere, sa se calculeze c.m.m.d.c. a n elemente intregi ale unei liste date.
9. Pentru fiecare element al unei liste de numere intregi date, sa se afiseze numarul prim cel mai apropiat de el ca valoare. Daca doua numere prime sunt la distanta egala de un element din lista se vor afisa ambele numere prime.
|