Noi te platim pentru timpul acordat , o postare , like , vizualizare subiect , sau creare subiect , insemna castig.
Suntem comunitatea unica din Romania care plateste pentru efortul depus . Ideile ,opiniile tale conteaza si sunt platite doar la noi.

Variabile

Variabile

Solus

Membru
Staff member
Fondator BitArena
Moderator
Utilizator
Joined
Jul 6, 2018
Messages
523
Reaction score
94
Points
26
Location
Bucuresti
Website
www.bitarena.eu

Reputation:

O variabilă este un obiect de programare căruia i se atribuie un nume.
Variabilele ca şi constantele sînt elemente de bază cu care operează un program scris în C.
Variabilele se deosebesc după denumire şi pot primi diferite valori. Numele variabilelor sînt identificatori. Numele de variabile se scriu de obicei cu litere mici (fără a fi obligatoriu).
Variabilele în limbajul C sînt caracterizate prin două atribute: clasă de memorie şi tip.
Aceste două atribute îi sînt atribuite unei variabile prin intermediul unei declaraţii. Declaraţiile listează variabilele care urmează a fi folosite, stabilesc clasa de memorie, tipul variabilelor şi eventual valorile iniţiale, dar despre declaraţii vom discuta în capitolul 5.

3.1. Clase de memorie


Limbajul C prezintă patru clase de memorie: automatică, externă, statică, registru.

Variabile automatice

Variabilele automatice sînt variabile locale fiecărui bloc (secţiunea 6.2) sau funcţii (capitolul 7). Ele se declară prin specificatorul de clasă de memorie auto sau implicit prin context. O variabilă care apare în corpul unei funcţii sau al unui bloc pentru care nu s-a făcut nici o declaraţie de clasă de memorie se consideră implicit de clasă auto.
O variabilă auto este actualizată la fiecare intrare în bloc şi se distruge în momentul cînd controlul a părăsit blocul. Ele nu îşi reţin valorile de la un apel la altul al funcţiei sau blocului şi trebuie iniţializate la fiecare intrare. Dacă nu sînt iniţializate, conţin valori reziduale. Nici o funcţie nu are acces la variabilele auto din altă funcţie. În funcţii diferite pot exista variabile locale cu aceleaşi nume, fără ca variabilele să aibă vreo legătură între ele.

Variabile externe


Variabilele externe sînt variabile cu caracter global. Ele se definesc în afara oricărei funcţii şi pot fi apelate prin nume din oricare funcţie care intră în alcătuirea programului.
În declaraţia de definiţie aceste variabile nu necesită specificarea nici unei clase de memorie.
La întîlnirea unei definiţii de variabilă externă compilatorul alocă şi memorie pentru această variabilă.
Într-un fişier sursă domeniul de definiţie şi acţiune al unei variabile externe este de la locul de declaraţie pînă la sfîrşitul fişierului.
Aceste variabile există şi îşi păstrează valorile de-a lungul execuţiei întregului program.
Pentru ca o funcţie să poată utiliza o variabilă externă, numele variabilei trebuie făcut cunoscut funcţiei printr-o declaraţie. Declaraţia poate fi făcută fie explicit prin utilizarea specificatorului extern, fie implicit prin context.
Dacă definiţia unei variabile externe apare în fişierul sursă înaintea folosirii ei într-o funcţie particulară, atunci nici o declaraţie ulterioară nu este necesară, dar poate fi făcută.
Dacă o variabilă externă este referită într-o funcţie înainte ca ea să fie definită, sau dacă este definită într-un fişier sursă diferit de fişierul în care este folosită, atunci este obligatorie o declaraţie extern pentru a lega apariţiile variabilelor respective.
Dacă o variabilă externă este definită într-un fişier sursă diferit de cel în care ea este referită, atunci o singură declaraţie extern dată în afara oricărei funcţii este suficientă pentru toate funcţiile care urmează declaraţiei.
Funcţiile sînt considerate în general variabile externe afară de cazul cînd se specifică altfel.
Variabilele externe se folosesc adeseori în locul listelor de argumente pentru a comunica date între funcţii, chiar dacă funcţiile sînt compilate separat.

Variabile statice


Variabilele statice se declară prin specificatorul de clasă de memorie static. Aceste variabile sînt la rîndul lor de două feluri: interne şi externe.
Variabilele statice interne sînt locale unei funcţii şi se definesc în interiorul unei funcţii, dar spre deosebire de variabilele auto, ele îşi păstrează valorile tot timpul execuţiei programului. Variabilele statice interne nu sînt create şi distruse de fiecare dată cînd funcţia este activată sau părăsită; ele oferă în cadrul unei funcţii o memorie particulară permanentă pentru funcţia respectivă.
Alte funcţii nu au acces la variabilele statice interne proprii unei funcţii.
Ele pot fi declarate şi implicit prin context; de exemplu şirurile de caractere care apar în interiorul unei funcţii cum ar fi argumentele funcţiei printf (vezi capitolul 11) sînt variabile statice interne.
Variabilele statice externe se definesc în afara oricărei funcţii şi orice funcţie are acces la ele. Aceste variabile sînt însă globale numai pentru fişierul sursă în care ele au fost definite. Nu sînt recunoscute în alte fişiere.
În concluzie, variabila statică este externă dacă este definită în afara oricărei funcţii şi este static internă dacă este definită în interiorul unei funcţii.
În general, funcţiile sînt considerate obiecte externe. Există însă şi posibilitatea să declarăm o funcţie de clasă static. Aceasta face ca numele funcţiei să nu fie recunoscut în afara fişierului în care a fost declarată.


Variabile registru

O variabilă registru se declară prin specificatorul de clasă de memorie register. Ca şi variabilele auto ele sînt locale unui bloc sau funcţii şi valorile lor se pierd la ieşirea din blocul sau funcţia respectivă. Variabilele declarate register indică compilatorului că variabilele respective vor fi folosite foarte des. Dacă este posibil, variabilele register vor li plasate de către compilator în regiştrii rapizi ai calculatorului, ceea ce conduce la programe mai compacte şi mai rapide.
Variabile register pot fi numai variabilele automatice sau parametrii formali ai unei funcţii. Practic există cîteva restricţii asupra variabilelor register care reflectă realitatea hardware-ului de bază. Astfel:
- numai cîteva variabile din fiecare funcţie pot fi păstrate în regiştri (de obicei 2 sau 3); declaraţia register este ignorată pentru celelalte variabile;
- numai tipurile de date int, char şi pointer sînt admise;
- nu este posibilă referirea la adresa unei variabile register.

3.2. Tipuri de variabile

Limbajul C admite numai cîteva tipuri fundamentale de variabile: caracter, întreg, flotant.

Tipul caracter

O variabilă de tip caracter se declară prin specificatorul de tip char. Zona de memorie alocată unei variabile de tip char este de un octet. Ea este suficient de mare pentru a putea memora orice caracter al setului de caractere implementate pe calculator.
Dacă un caracter din setul de caractere este memorat într-o variabilă de tip char, atunci valoarea sa este egală cu codul întreg al caracterului respectiv. Şi alte cantităţi pot fi memorate în variabile de tip char, dar implementarea este dependentă de sistemul de calcul.
Ordinul de mărime al variabilelor caracter este între -128 şi 127. Caracterele setului ASCII sînt toate pozitive, dar o constantă caracter specificată printr-o secvenţă de evitare poate fi şi negativă, de exemplu '\377' are valoarea -1. Acest lucru se întîmplă atunci cînd această constantă apare într-o expresie, moment în care se converteşte la tipul int prin extensia bitului cel mai din stînga din octet (datorită modului de funcţionare a instrucţiunilor calculatorului).

Tipul întreg


Variabilele întregi pozitive sau negative pot fi declarate prin specificatorul de tip int. Zona de memorie alocată unei variabile întregi poate fi de cel mult trei dimensiuni.
Relaţii despre dimensiune sînt furnizate de calificatorii short, long şi unsigned, care pot fi aplicaţi tipului int.
Calificatorul short se referă totdeauna la numărul minim de octeţi pe care poate fi reprezentat un întreg, în cazul nostru 2.
Calificatorul long se referă la numărul maxim de octeţi pe care poate fi reprezentat un întreg, în cazul nostru 4.
Tipul int are dimensiunea naturală sugerată de sistemul de calcul. Scara numerelor întregi reprezentabile în maşină depinde de asemenea de sistemul de calcul: un întreg poate lua valori între -32768 şi 32767 (sisteme de calcul pe 16 biţi) sau între -2147483648 şi 2147483647 (sisteme de calcul pe 32 de biţi).
Calificatorul unsigned alături de declaraţia de tip int determină ca valorile variabilelor astfel declarate să fie considerate întregi fără semn.
Numerele de tipul unsigned respectă legile aritmeticii modulo 2n, unde n este numărul de biţi din reprezentarea unei variabile de tip int. Numerele de tipul unsigned sînt totdeauna pozitive.
Declaraţiile pentru calificatori sînt de forma:
short int x;
long int y;
unsigned int z;
Cuvîntul int poate fi omis în aceste situaţii.

Tipul flotant (virgulă mobilă)


Variabilele flotante pot fi în simplă precizie şi atunci se declară prin specificatorul de tip float sau în dublă precizie şi atunci se declară prin specificatorul double. Majoritatea sistemelor de calcul admit şi reprezentarea în precizie extinsă; o variabilă în precizie extinsă se declară prin specificatorul long double.

Tipul void (tip neprecizat)


Un pointer poate fi declarat de tip void. În această situaţie pointerul nu poate fi folosit pentru indirectare (dereferenţiere) fără un cast explicit, şi aceasta deoarece compilatorul nu poate determina mărimea obiectului pe care pointerul îl indică.

int x;
float r;
void *p = &x; /* p indică pe x */
int main() {
*(int *) p = 2;
p = &r; /* p indică pe r */
*(float *)p = 1.1;
}

Dacă o funcţie este declarată de tip void, aceasta nu va returna o valoare:

void hello(char *name) {
printf("Hello, %s.",name);
}

Tipuri derivate


În afară de tipurile aritmetice fundamentale, există, în principiu, o clasă infinită de tipuri derivate, construite din tipurile fundamentale în următoarele moduri:
– „masive de T” pentru masive de obiecte de un tip dat T, unde T este
unul dintre tipurile admise;
– „funcţii care returnează T” pentru funcţii care returnează obiecte de un tip dat T;
– „pointer la T” pentru pointeri la obiecte de un tip dat T;
– „structuri” pentru un şir de obiecte de tipuri diferite;
– „reuniuni” care pot conţine obiecte de tipuri diferite, tratate într-o singură zonă de memorie.
În general aceste metode de construire de noi tipuri de obiecte pot fi aplicate recursiv. Amănunte despre tipurile derivate sînt date în secţiunea 5.3.

3.3. Obiecte şi valori-stînga

Alte două noţiuni folosite în descrierea limbajului C sînt obiectul şi valoarea-stînga.
Un obiect este conţinutul unei zone de memorie.
O valoare-stînga este o expresie care se referă la un obiect. Un exemplu evident de valoare-stînga este un identificator. Există operatori care produc valori-stînga: de exemplu, dacă E este o expresie de tip pointer, atunci *E este o expresie valoare-stînga care se referă la obiectul pe care-l indică E. Numele valoare-stînga (în limba engleză left value) a fost sugerat din faptul că în expresia de atribuire E1 = E2 operandul stîng E1 trebuie să fie o expresie valoare-stînga. În paragraful de descriere a operatorilor se va indica dacă operanzii sînt valori-stînga sau dacă rezultatul operaţiei este o valoare-stînga.

3.4. Conversii de tip

Un număr mare de operatori pot cauza conversia valorilor unui operand de la un tip la altul. Dacă într-o expresie apar operanzi de diferite tipuri, ei sînt convertiţi la un tip comun după un mic număr de reguli. În general se fac automat numai conversiile care an sens, de exemplu: din întreg în flotant, într-o expresie de forma f+i. Expresii care nu au sens, ca de exemplu un număr flotant ca indice, nu sînt admise.

Caractere şi întregi


Un caracter poate apărea oriunde unde un întreg este admis. În toate cazurile valoarea caracterului este convertită automat într-un întreg. Deci într-o expresie aritmetică tipul char şi int pot apărea împreună. Aceasta permite o flexibilitate considerabilă în anumite tipuri de transformări de caractere. Un astfel de exemplu este funcţia atoi descrisă în secţiunea 7.5 care converteşte un şir de cifre în echivalentul lor numeric.
Expresia:
s - '0'
produce valoarea numerică a caracterului (cifră) memorat în ASCII.
Atragem atenţia că atunci cînd o variabilă de tip char este convertită la tipul int, se poate produce un întreg negativ, dacă bitul cel mai din stînga al octetului conţine 1. Caracterele din setul de caractere ASCII nu devin niciodată negative, dar anumite configuraţii de biţi memorate în variabile de tip caracter pot apărea ca negative prin extensia la tipul int.
Conversia tipului int în char se face cu pierderea biţilor de ordin superior.
Întregii de tip short sînt convertiţi automat la int. Conversia întregilor se face cu extensie de semn; întregii sînt totdeauna cantităţi cu semn.
Un întreg long este convertit la un întreg short sau char prin trunchiere la stînga; surplusul de biţi de ordin superior se pierde.


Conversii flotante

Toate operaţiile aritmetice în virgulă mobilă se execută în precizie extinsă. Conversia de la float la int se face prin trunchierea părţii fracţionare. Conversia de la int la float este acceptată.

Întregi fără semn


Într-o expresie în care apar doi operanzi, dintre care unul unsigned iar celălalt un întreg de orice alt tip, întregul cu semn este convertit în întreg fără semn şi rezultatul este un întreg fără semn.
Cînd un int trece în unsigned, valoarea sa este cel mai mic întreg fără semn congruent cu întregul cu semn (modulo 216 sau 232). Într-o reprezentare la complementul faţă de 2 (deci pentru numere negative), conversia este conceptuală, nu există nici o schimbare reală a configuraţiei de biţi.
Cînd un întreg fără semn este convertit la long, valoarea rezultatului este numeric aceeaşi ca şi a întregului fără semn, astfel conversia nu face altceva decît să adauge zerouri la stînga.

Conversii aritmetice


Dacă un operator aritmetic binar are doi operanzi de tipuri diferite, atunci tipul de nivel mai scăzut este convertit la tipul de nivel mai înalt înainte de operaţie. Rezultatul este de tipul de nivel mai înalt. Ierarhia tipurilor este următoarea:


    • – char < short < int < long;
    • – float < double < long double;
– tip întreg cu semn < tip întreg fără semn;
– tip întreg < virgulă mobilă.


Conversii prin atribuire

Conversiile de tip se pot face prin atribuire; valoarea membrului drept este convertită la tipul membrului stîng, care este tipul rezultatului.

Conversii logice

Expresiile relaţionale de forma i<j şi expresiile logice legate prin operatorii && şi || sînt definite ca avînd valoarea 1 dacă sînt adevărate şi 0 dacă sînt false.
Astfel atribuirea:
d = (c>='0') && (c<='9');
îl face pe d egal cu 1 dacă c este cifră şi egal cu 0 în caz contrar.

Conversii explicite


Dacă conversiile de pînă aici le-am putea considera implicite, există şi conversii explicite de tipuri pentru orice expresie. Aceste conversii se fac prin construcţia specială numită cast de forma:
(nume-tip) expresie
În această construcţie expresie este convertită la tipul specificat după regulile precizate mai sus. Mai precis aceasta este echivalentă cu atribuirea expresiei respective unei variabile de un tip specificat, şi această nouă variabilă este apoi folosită în locul întregii expresii. De exemplu, în expresia:
sqrt((double)n)
se converteşte n la double înainte de a se transmite funcţiei sqrt. Notăm însă că, conţinutul real al lui n nu este alterat. Operatorul cast are aceeaşi precedenţă ca şi oricare operator unar.

Expresia constantă


O expresie constantă este o expresie care conţine numai constante. Aceste expresii sînt evaluate în momentul compilării şi nu în timpul execuţiei; ele pot fi astfel utilizate în orice loc unde sintaxa cere o constantă, ca de exemplu:

#define MAXLINE 1000
char line[MAXLINE+1];
 
Top