Sunteți pe pagina 1din 23

InfoAcademy Adonis Butufei

3 VARIABILE

CUPRINS
3 Variabile......................................................................................................................................................2
3.1 Dimensiunea variabilelor....................................................................................................................2
3.1.1Biti si octeti...................................................................................................................................2
3.1.2Determinarea numarului de octeti pentru variabile - operatorul sizeof........................................2
3.1.3 Reprezentarea numerelor in baza 2 (binar)..................................................................................3
3.1.4Reprezentarea numerelor in baza 16 (hexazecimala)...................................................................3
3.1.4.1 Initializarea variabilelor intregi cu valori hexazecimale......................................................4
3.1.4.2 Unde se foloseste reprezentarea hexazecimala....................................................................4
3.1.5Reprezentarea numerelor in baza 8 (octal)...................................................................................5
3.2 Domeniul de viata al variabilelor........................................................................................................5
3.2.1Locul declararii variabilelor si influenta acestuia asupra domeniului de viata............................5
3.2.1.1 Mascarea variabilelor...........................................................................................................6
3.2.1.2 Domeniul de viata al variabilelor si apelul functiilor..........................................................7
3.2.2Calificatorii de context.................................................................................................................8
3.2.2.1 Calificatorul auto.................................................................................................................8
3.2.2.2 Calificatorul register............................................................................................................8
3.2.2.3 Calificatorul extern..............................................................................................................8
3.2.2.4 Calificatorul static................................................................................................................8
3.3 Variabile numerice...............................................................................................................................9
3.3.1Variabile intregi..........................................................................................................................10
3.3.1.1 Calculul dimensiunii necesare pentru stocarea variabilelor intregi pozitive.....................10
3.3.1.2 Procesarea semnului..........................................................................................................10
3.3.1.3 Calificatori de semn...........................................................................................................11
3.3.1.4 Calificatori de marime.......................................................................................................11
3.3.1.5 Limitele variabilelor intregi...............................................................................................11
3.3.1.6 Depasirea limitelor.............................................................................................................13
3.3.2Variabile reale.............................................................................................................................13
3.3.2.1 Tipuri de variabile reale suportate de C++.........................................................................14
3.3.2.2 Moduri de scriere a numerelor reale..................................................................................14
3.3.2.3 Intializarea variabilelor reale.............................................................................................14
3.3.2.4 Testarea egalitatii pentru variabilele reale.........................................................................15
3.3.2.5 Limitele variabilelor reale..................................................................................................16
3.4 Variabile de tip caracter.....................................................................................................................17
3.4.1.1 Afisarea codurilor ASCII pe ecran.....................................................................................17
3.4.1.2 Citirea valorilor tip caracter de la tastatura........................................................................18
3.4.1.3 Categorii de coduri ASCII.................................................................................................18
3.5 Aliasuri de tipuri................................................................................................................................20
3.6 Sumar................................................................................................................................................20
3.7 Intrebari si exercitii...........................................................................................................................21
3.8 Bibliografie.......................................................................................................................................23

1
Adonis Butufei

3 VARIABILE
In acest capitol vom discuta despre:
• Dimensiunea variabilelor: cum se determina dimensiunea variabilelor folosind operatorul sizeof, ce
legatura este intre dimensiunea variabilelor si intervalul de valori cu care lucreaza acea variabila, baze
de numeratie.
• Variabile de tip caracter, codurile ASCII, categorii de caractere si secvente escape.
• Variabile de tip numeric, procesarea semnului, limitele intervalelor de valori pentru fiecare tip de date
standard folosite in C++ si conversia tipurilor de date.
• Domeniul de viata al variabilelor.

3.1 Dimensiunea variabilelor


In capitolul precedent am vazut ca o variabila reprezinta o zona de memorie. Cantitatea de memorie
rezervata de compilator pentru acea variabila este determinata de tipul de variabila. In acest paragraf vom
studia in detaliu corelatia dintre valoarea datelor si dimensiunea variabilelor.

3.1.1 Biti si octeti


Calculatoarele au fost construite sa proceseze informatia binara. Elementul cel mai mic de informatie
binara este bitul. Acesta poate avea doua valori: 1 sau 0. Pentru a putea reprezenta date reale este necesara
folosirea mai multor biti simultan.
Deoarece reprezentarea textului a fost una dintre primele probleme adresate de calculatoare si pentru
reprezentarea unui caracter au fost necesari 8 biti acesta a devenit etalonul pentru reprezentarea datelor.

O grupare de 8 biti reprezinta un octet sau un byte.


Din motive de arhitectura hardware dimensiunea variabilelor este reprezentata prin multiplii intregi de
octeti. Limbajul C++ are tipuri predefinite de variabile care au uzual 1, 2, 4, 8 octeti.

3.1.2 Determinarea numarului de octeti pentru variabile - operatorul sizeof


Pentru a determina numarul de octeti asociat unei variabile se foloseste operatorul sizeof, ca in urmatorul
exemplu:

#include <iostream>
using namespace std;

int main()
{
cout << sizeof(int) << "\n";
}

2
InfoAcademy Adonis Butufei

3.1.3 Reprezentarea numerelor in baza 2 (binar)


In activitatile zilnice suntem obisnuiti cu reprezentarea zecimala a numerelor. Inainte de a explora
reprezentarea binara a numerelor sa aruncam o privire asupra modului in care folosim baza zecimala.
Orice numar de 4 cifre, de exemplu, se poate reprezenta in modul urmator:

3 2 1 0
abcd 10 =a∗10 + b∗10 + c∗10 + d∗10

Unde a, b, c si d pot lua valori in intervalul [0 – 9].


Acelasi numar se poate reprezenta in baza 2 cu ajutorul formulei:
(abcd )10=b n∗2 n+ b n−1∗2n−1+ ⋯+ b1∗21+ b0∗20 =( bn b n−1⋯b1 b 0)2

Unde b n , b n−1⋯ , b0 apartin intervalului [0, 1].


Bitul b n se numeste cel mai semnificativ bit1 iar bitul b 0 se numeste cel mai putin semnificativ bit2.

Exemple:
(0)10=0∗2 1+ 0∗2 0=(00)2
(1)10=0∗21+ 1∗20 =( 01)2
(2)10=1∗21+ 0∗20=(10)2
(3)10=1∗21+ 1∗20=(11)2

3.1.4 Reprezentarea numerelor in baza 16 (hexazecimala)


In paragrafele anterioare am vazut ca pentru reprezentarea datelor se folosesc unul sau mai multi octeti.
De asemenea, am inteles ca aceste date sunt reprezentate in baza 2 pentru a putea fi procesate de
calculator. Ne-am putea intreba care este utilitatea folosirii bazei 16? Sa examinam reprezentarea binara a
unui octet:
b 7 b6 b5 b 4 b3 b2 b 1 b 0
Aceasta forma este greu de urmarit (pentru oameni) si din acest motiv a fost organizata in doua grupuri de
4 biti. Fiecare grup de 4 biti poate fi reprezentat foarte usor in baza 16 dupa cum urmeaza:
∣b 7 b6 b5 b 4∣∣b 3 b 2 b1 b0∣≡h 1 h 0
Codurile numerelor pentru reprezentarea zecimala, binara si hexazecimala sunt prezentate in tabelul de
mai jos.
Zecimal Binar Hexazecimal
0 0000 0
1 0001 1
2 0010 2
3 0011 3

1 In literatura de specialitate il putem intalni sub acronimul MSB most significant bit.

2 In literatura de specialitate il putem intalni sub acronimul LSB least significant bit.
3
Adonis Butufei

Zecimal Binar Hexazecimal


4 0100 4
5 0101 5
6 0110 6
7 0111 7
8 1000 8
9 1001 9
10 1010 A
11 1011 B
12 1100 C
13 1101 D
14 1110 E
15 1111 F

Exemple:
Zecimal Binar Hexazecimal

255 11111111 FF = 15∗16 115∗16 0

62 00111110 3E = 3∗16 114∗160

74 01001010 4A = 4∗16110∗16 0

Se observa ca plecand de la codurile hexazecimale se poate verifica foarte usor reprezentarea binara.

3.1.4.1 Initializarea variabilelor intregi cu valori hexazecimale


Initializarea se poate face folosind notatia 0xValoareHexa ca in exemplele urmatoare:
short flag = 0x00F1; // Initializarea unei variabile de 2 octeti.
char mask = 0xA2; // Initializarea unei variabile de un octet.

3.1.4.2 Unde se foloseste reprezentarea hexazecimala


Cel mai des, reprezentarea hexazecimala se foloseste pentru:
- Specificarea adreselor de memorie. Aceasta este utila pentru depanarea programelor care manipuleaza
adresele variabilelor.
- Setarea valorilor variabilelor la nivel de bit.
Exemplu:
const short OK = 0x00;

4
InfoAcademy Adonis Butufei

3.1.5 Reprezentarea numerelor in baza 8 (octal)


Aceasta reprezentare se poate gandi in mod asemanator cu reprezentarea binara si cea hexazecimala.
A fost folosita inaintea notatiei hexazecimale. In prezent este utilizata pentru setarea drepturilor de acces
in sistemele de operare UNIX/Linux si probabil pentru intretinerea programelor mai vechi.

Initializarea variabilelor se face folosind 0 inaintea valorii, ca in exemplul de mai jos:


int octalExample = 0123;

3.2 Domeniul de viata al variabilelor


O variabila are un domeniu de viata care reprezinta zona de cod in care este accesibila pe parcursul
executiei unui program.
Domeniul de viata al variabilelor este determinat de modul in care se face declararea acelor variabile.
Declararea variabilelor influenteaza domeniul de viata prin locul unde se face declararea si prin
calificatori.

3.2.1 Locul declararii variabilelor si influenta acestuia asupra domeniului de viata


Dupa locul de declarare, exista doua tipuri de variabile: locale si globale.
Variabilele locale sunt declarate in interiorul unui bloc de instructiuni si sunt accesibile in acel bloc si in
blocurile incluse in acesta. Atunci cand executia programului depaseste blocul in care au fost definite,
memoria ocupata este eliberata automat si numele acelor variabile este desfiintat.
Variabilele globale sunt declarate in afara oricarui bloc de instructiuni si sunt accesibile pe toata durata
executarii programului.
Exemplu:
int global = 0; // Aceasta variabila este globala,
// ea este accesibila pe toata durata
// executarii programului.

int main()
{
int total = 0; // Aceasta variabila este accesibila
// in interiorul functiei main.

for(int i = 0; i < 10; i = i + 1)


{
// Variabila i este accesibila in interiorul blocului for.
total = total + i; // putem folosi variabila total
// deoarece blocul for apartine
// functiei main.
}

5
Adonis Butufei

return 0;
}

Daca incercam sa folosim o variabila in afara domeniului ei obtinem o eroare de compilare ca in exemplul
de mai jos:
int main()
{
int total;
for(int i = total; i < 10; i = i + 1)
{
total = total + i;
}

int lastIndex = i; // se obtine eroare de compilare

return 0;
}

Recomandare
Pentru reducerea defectelor programelor este bine ca variabilele sa aiba cel mai mic domeniu de viata.
Acesta este un mod defensiv care asigura eliberarea memoriei nefolosite si reduce cuplajul prin date3
care poate crea defecte greu de depistat.

3.2.1.1 Mascarea variabilelor


Apare atunci cand declaram intr-un bloc o variabila cu nume identic cu cel al unei variabile declarate
intr-un bloc parinte. Atunci cand se intampla acest lucru, compilatorul afiseaza doar un mesaj de
avertizare (warning), insa putem compila si rula programul.
Exemplu:
1: #include <iostream>
2: using namespace std;
3:
4: int main()
5: {
6: int total = 0;
7:
8: {
9: int total = 0; // mascheaza variabila total
// declarata in blocul parinte.
10:
11: for(int i = 0; i < 10; i = i + 1)
12: {

3 Cuplajul prin date apare atunci cand mai multe functii folosesc aceleasi variabile globale.
6
InfoAcademy Adonis Butufei

13: total = total + i;


14: }
15:
16: cout << total << "\n"; // avem rezultatul asteptat
17: }
18:
19: cout << total << "\n"; // aceasta variabila are valoarea 0
20: return 0;
21: }

In linia 6 am declarat o variabila total care are domeniul de viata functia main. Pe linia 9 am definit o alta
variabila total care are ca domeniu de viata acest bloc si blocurile descendente si care mascheaza variabila
total definita in linia 6.
Bucla dintre liniile 11 – 14 lucreaza cu aceasta variabila, Atunci cand se termina executia blocului,
memoria pentru variabila declarata aici este eliberata si rezultatul se pierde.

Mascarea variabilelor poate genera defecte foarte greu de depanat si trebuie evitata. Folosind variabile
cu domenii de viata cat mai mici este usor de identificat acest fenomen.

3.2.1.2 Domeniul de viata al variabilelor si apelul functiilor


Functiile pot accesa variabile globale si locale. Interactiunea cu functia se face prin intermediul
parametrilor si al valorii returnate. Cuplajul prin intermediul variabilelor globale este bine sa fie evitat.
Exemplul de mai jos ilustreaza aceste aspecte:
1: int total;
2:
3: int sum(int a, int b)
4: {
5: return a + b;
6: }
7:
8: void badsum(int a, int b)
9: {
10: total = a + b;
11: }
12:
13: int main()
14: {
15: int result = sum(2,3);
16: badsum(4,5);
17: return 0;
18: }

7
Adonis Butufei

In prima linie am declarat o variabila globala total. Functia sum calculeaza suma parametrilor a si b si
returneaza rezultatul. Functia badsum atribuie rezultatul sumei variabilei globale creand un cuplaj prin
date.
Daca o alta functie schimba valoarea acestei variabile intre punctul de apel si cel in care se foloseste
rezultatul, executia este incorecta.

Parametri transmisi unei functii sunt considerati variabile locale si pot fi folositi ca si cum ar fi fost
declarati in corpul functiei.

3.2.2 Calificatorii de context


In capitolul anterior am discutat ca pentru declararea variabilelor sunt necesare doua elemente: tipul
variabilei si numele acesteia. Acum vom examina al treilea element care este reprezentat de calificatori.
Pentru specificarea locului unde se va stoca variabila, exista patru calificatori: auto, static, extern
si register.

3.2.2.1 Calificatorul auto


Este calificatorul implicit. Atunci cand nu este specificat, compilatorul foloseste acest calificator.
Exemplu:
auto int test;

3.2.2.2 Calificatorul register


Acest calificator este folosit pentru variabile care sunt tinute in registrii procesorului. Folosirea unei variabile in registrul
procesorului poate imbunatati performanta executiei4.
Exemplu:
register int processorRegister = 0;

3.2.2.3 Calificatorul extern


Acest calificator spune compilatorului ca variabila respectiva a fost definita in alt fisier. In acest fel putem
folosi variabile globale definite in alte fisiere.
Exemplu:
extern int totalIncome;

3.2.2.4 Calificatorul static


Acest calificator are doua intelesuri:
1. Daca este folosit pentru variabilele globale, el restrange domeniul de viata la fisierul in care sunt
declarate.
2. Daca se refera la variabilele locale, atunci memoria variabilei nu mai este dealocata dupa executia

4 Se recomanda masurarea precisa a performantei si identificarea portiunilor care necesita optimizarea performantei.
Optimizarea prematura a performantei este o sursa de probleme si poate genera un cod greu de mentiut.
8
InfoAcademy Adonis Butufei

codului.

Urmatoarele exemple ilustreaza folosirea calificatorului static:

1: static int variabilaGlobala; // accesibila doar in fiserul curent.


2:
3: int main()
4: {
5: // instructiuni.
6: return 0;
7: }

Variabila globala definita in acest fisier are domeniul de viata in acest fisier, Daca se incearca accesarea ei
din alt fisier folosind o declaratie: extern int variabilaGlobala; se obtine o eroare de compilare.

1: #include <iostream>
2: using namespace std;
3:
4: void ExempluVariabilaStatica()
5: {
6: static int nrApeluri = 1; // Se executa doar la primul apel.
7:
8: cout << "Numarul apelurilor functiei:"
9: << nrApeluri << "\n";
10:
11: nrApeluri = nrApeluri + 1;
12: }
13:
14: int main()
15: {
16: ExempluVariabilaStatica();
17: ExempluVariabilaStatica();
18:
19: return 0;
20: }

In acest exemplu linia 6 se executa doar la prima rulare. Apelurile succesive ale functiei incrementeaza
variabila si, in acest caz, putem calcula numarul apelurilor.

3.3 Variabile numerice


Pana acum au fost prezentate principiile generale de reprezentare a variabilelor in memorie si domeniul
9
Adonis Butufei

lor de viata. Acum vom examina in detaliu tipurile de variabile intregi si reale, intervalele de valori si
dimensiunea zonei de memorie in octeti necesara pentru aceste variabile.

3.3.1 Variabile intregi

3.3.1.1 Calculul dimensiunii necesare pentru stocarea variabilelor intregi pozitive


Cati biti sunt necesari pentru a reprezenta numerele intregi?
Observam din exemplele anterioare ca pentru reprezentare numerelor de la 0 la 15 sunt suficienti 4 biti.
Se poate demonstra matematic urmatoarea relatie:
Cu ajutorul a n biti putem reprezenta numere intregi pozitive in baza 10 in intervalul:
[0−(2 n−1)]

Exemplu:
In cazul unui octet putem stoca numere pozitive cuprinse intre 0 si 2 8−1 adica in intervalul [0, 255].

Ce se intampla daca o variabila are valoarea maxima si o incrementam? Ce ar indica kilometrajul


automobilului dupa ce toate cifrele au ajuns la 9? Am incepe de la 0. Acelasi lucru se intampla si cu
variabila.

Important
• Atunci cand una dintre limitele intervalului este depasita cu o unitate prin incrementare sau
decrementare urmatoarea valoare va fi cealalta limita a intervalului.
• Putem gandi valorile unui interval dispuse pe un cerc. Dupa o rotatie completa in oricare sens valorile
se repeta.
• Acest aspect este foarte important la bucle: daca valoarea din conditia de oprire a buclei nu este in
intervalul variabilei utilizate pentru testul buclei, vom avea fie o bucla infinita, fie secventa buclei nu
se va executa niciodata.

3.3.1.2 Procesarea semnului


In momentul cand vrem sa lucram cu numere pozitive si negative, vom translata intervalul calculat cu
formula anterioara catre stanga astfel incat jumatate din numere sa fie negative si jumatate pozitive.
Aceasta presupune injumatatirea limitei maxime.

Exemplu:
Pentru un octet am avea limita maxima pozitiva de 2 7−1 adica 127, iar limita inferioara va fi de
−27 adica -128. Pe un octet putem stoca numere cuprinse in intervalul [-128, 127].

Important
Sa presupunem ca avem o variabila de marimea unui octet care are valoarea 127 si o incrementam. Si in
aceasta situatie se aplica observatiile anterioare. Noua valoare va fi -128. Iar daca variabila are valoarea
-128 si o decrementam noua valoare va fi 127.
10
InfoAcademy Adonis Butufei

3.3.1.3 Calificatori de semn


In mod implicit variabilele sunt cu semn. Pentru a informa compilatorul ca dorim ca variabila noastra sa
fie fara semn trebuie sa folosim calificatorul unsigned ca in exemplul de mai jos.
unsigned int contor;
In acest caz variabila va avea numai valori pozitive.

3.3.1.4 Calificatori de marime


Am vazut ca tipul variabilei determina intervalul de valori pe care o variabila le poate lua. Pentru a
informa compilatorul cati octeti dorim pentru variabila noastra intreaga folosim calificatorii prezentati in
tabelul de mai jos:
Calificator Dimensiune in octeti Exemplu
short 2 short intreg16b = 16;
int 4 int intreg32b = 32;
long 4 long intreg32b = 32;
long long 8 long long intreg64b = 64

3.3.1.5 Limitele variabilelor intregi


Am discutat pana acum despre limitele variabilelor si am vazut ca ele sunt de terminate de numarul de
octeti si de modul in care se proceseaza semnul. Aceste limite sunt definite in fisierul <climits> si sunt
prezentate in tabelul de mai jos:

Tip Limta Valoare Explicatii


char SCHAR_MIN (-128) valoare minima a tipului
char
char SCHAR_MAX 127 valoare maxima a tipului
caracter cu semn
char UCHAR_MAX 0xff valoare maxima a tipului
caracter fara semn
char CHAR_MIN SCHAR_MIN sau 0 valoare minima a tipului
caracter
char CHAR_MAX SCHAR_MAX sau valoare maxima a tipului
UCHAR_MAX caracter (cu semn sau
fara
short SHRT_MIN (-32768) valoare minima a tipului
intreg (cu semn) short

11
Adonis Butufei

short SHRT_MAX 32767 valoare maxima a tipului


intreg (cu semn) short
unsigned short USHRT_MAX 0xffff valoare maxima a tipului
intreg (fara semn) short
int INT_MIN (-2147483647 - 1) valoare minima a tipului
intreg (cu semn)
int INT_MAX 2147483647 valoare maxima a tipului
intreg (cu semn)
unsigned UINT_MAX 0xffffffff valoare maxima a tipului
intreg (fara semn)
long LONG_MIN (-2147483647L - 1) valoare minima a tipului
long (cu semn)
long LONG_MAX 2147483647L valoare maxima a tipului
long (cu semn)
unsigned long ULONG_MAX 0xffffffffUL valoare maxima a tipului
long (fara semn)
long long LLONG_MAX 9223372036854775807i64 valoare maxima a tipului
long long (cu semn)
long long LLONG_MIN (- valoare minima a tipului
9223372036854775807i64 - long long (cu semn)
1)
unsigned long long ULLONG_MAX 0xffffffffffffffffui64 valoare maxima a tipului
long long (fara semn)

Urmatorul exemplu afiseaza valorile limitelor pentru variabile de tip int.


#include <iostream>
#include <climits>
using namespace std;

int main()
{
cout << "Valoarea minima pentru int: " << INT_MIN << "\n";
cout << "Valoarea minima pentru int: " << INT_MAX << "\n";
cout << "Valoarea maxima pentru unsigned int: " << UINT_MAX << "\n";

return 0;
}

12
InfoAcademy Adonis Butufei

3.3.1.6 Depasirea limitelor5


Cand vrem sa stocam intr-o variabila o valoare care depaseste limitele intervalului specificat pentru acea
variabila, valoarea va fi trunchiata si programul va functiona incorect.

Exemplu:
1: unsigned short v1;
2: // ...
3: short v2 = v1;

Atribuirea din linia 3 necesita multa atentie. Daca valoarea variabilei v1 depaseste limita SHRT_MAX,
atunci este posibil ca functionarea sa fie defectuoasa.

Acest fenomen poate apare atunci cand se face atribuirea intre doua variabile de tip diferit sau cand o
variabila este folosita pentru a calcula suma sau produsul unei secvente de valori.

Cunoasterea acestui aspect este esentiala pentru alegerea tipurilor de variabile si scrierea codului
de calitate.

3.3.2 Variabile reale6


Daca ar fi sa folosim numai variabile intregi pentru efectuarea calculelor este ca si cum am incerca sa
construim o sfera din caramizi. La nivel de detaliu ar lipsi finetea reprezentarii.

Pe de alta parte, daca am folosi numai variabile reale pentru efectuarea calculelor este ca si cum am
incerca sa construim un cub din plastilina. Oricat de mult ne-am stradui nu am obtine muchiile drepte si
precise.

Pentru efectuarea calculelor cu numere reale au trebuit rezolvate doua probleme importante: posibilitatea
de a lucra cu intervale foarte mari de valori si reprezentarea acestor valori intr-o dimensiune predefinita
de memorie.

Pentru adresarea acestor necesitati nu se putea folosi o reprezentare exacta ca in cazul variabilelor intregi
ci s-a folosit o reprezentare aproximativa suficient de precisa a numerelor reale folosind un numar
standard de octeti7.

Deoarece analiza reprezentarii in memorie a variabilelor reale depaseste scopul cursului, in continuare
vom schita aspectele necesare intelegerii principiilor de functionare a numerelor reale.
Variabilele reale au trei elemente: semnul, o fractie zecimala si un exponent:
y=± f . f 1 f 2 … f n x 2exponent
Unde f.f 1 f 2 … f n este fractia zecimala.

5 In limba engleza se foloseste termenul overflow.


6 In limba engleza se foloseste termenul floating point pentru acest tip de variabile.
7 Reprezentarile uzuale sunt de 4, 8 sau 16 biti in functie de sistemul de operare.
13
Adonis Butufei

3.3.2.1 Tipuri de variabile reale suportate de C++


Pentru lucrul cu numere reale C++ ofera trei tipuri de date: float, double si long double.
Caracteristicile acestor tipuri sunt prezentate in tabelul de mai jos:
Tip Explicatie Numar de octeti
float numar real in precizie simpla 4
double numar real in precizie dubla 8

3.3.2.2 Moduri de scriere a numerelor reale


Pentru scrierea numerelor reale in C++ se folosesc doua moduri: modul stiintific si modul zecimal sau
notatia E.

Pentru a separa partea intreaga de partea zecimala, in C++ folosim caracterul punct . in loc de virgula ,.
Exemple:
3.54
0.37
-42.8

Modul stiintific foloseste forma ±abE±cd care este echivalenta cu ±ab x 10±cd . In aceasta notatie
putem folosi ambele litere (E) sau (e).

Exemple:
3e+2 = 3x102 = 300
3.24e-3= 3.24x10−3

De retinut
Nu trebuie sa existe spatii intre caractere atunci cand se foloseste aceasta notatie. Urmatoarele valori sunt
incorecte:
3 e+4
-4.5 e-2

3.3.2.3 Intializarea variabilelor reale


Initializarea variabilelor se face direct pentru variabilele double, iar pentru cele float trebuie pus f la
sfarsitul valorii.

Exemple:

14
InfoAcademy Adonis Butufei

float temp = 1.5f;


float y = -3.2e-5f;
double sum = 0.0;
double x = 1.23e5;

3.3.2.4 Testarea egalitatii pentru variabilele reale


Datorita aproximarii valorilor conditiile de egalitate nu se pot verifica folosind operatorul (==).
In exemplul urmator observam cum adunand de 10 ori valoarea 0.1 aceasta nu devine egala cu 1.0 asa
cum ne-am astepta.
#include <iostream>
using namespace std;

int main()
{
double sum = 0.0;
for(int i =0; i < 10; i = i + 1)
{
sum = sum + 0.1;
}

if(1.0 == sum)
{
cout << "suma este 1.0\n";
}
else
{
cout << "suma nu este 1.0\n";
}
return 0;
}

La rulare acest program intra pe ramura else si mesajul afisat este:


suma nu este 1.0

Pentru a compara variabilele reale este necesar sa calculam diferenta absoluta a valorii celor doua
variabile si daca aceasta diferenta este mai mica decat un nivel de eroare considerat acceptabil atunci
numerele sunt considerate egale. Programul urmator exemplifica aceasta idee:
#include <iostream>
#include <cmath>

15
Adonis Butufei

using namespace std;

bool AreEqual(double x, double y)


{
const double EPSILON = 1e-10;
return abs(x - y) < EPSILON;
}

int main()
{
double sum = 0.0;
for(int i =0; i < 10; i = i + 1)
{
sum = sum + 0.1;
}

if(AreEqual(1.0, sum))
{
cout << "suma este 1.0\n";
}
else
{
cout << "suma nu este 1.0\n";
}
}

Aici am inclus fisierul <cmath> pentru a putea folosi functia abs;


Important
Datorita erorilor de aproximare nu este recomandata folosirea variabilelor reale in programe pentru
calcule financiare.

3.3.2.5 Limitele variabilelor reale


Pentru a folosi aceste limite este necesara includerea fisierului <cfloat>. In urmatorul tabel sunt prezentate
constantele uzuale care pot fi utilizate pentru verificarea conditiilor.
Constante pentru double

Constanta Valoare Explicatie

DBL_DIG 15 Numar de cifre semnificative

DBL_EPSILON 2.2204460492503131e-016 Cea mai mica valoare pentru care


1.0+DBL_EPSILON != 1.0

DBL_MAX 1.7976931348623158e+308 Valoarea maxima

16
InfoAcademy Adonis Butufei

DBL_MAX_10_EXP 308 Exponentul maxim in baza 10

DBL_MIN 2.2250738585072014e-308 Valoarea pozitiva minima

DBL_MIN_10_EXP (-307) Exponentul minim in baza 10

Constante pentru float

FLT_DIG 6 Numar de cifre semnificative


FLT_EPSILON 1.192092896e-07F Cea mai mica valoare pentru care
1.0F+FLT_EPSILON != 1.0

FLT_MAX 3.402823466e+38F Valoarea maxima

FLT_MAX_10_EXP 38 Exponentul maxim in baza 10

FLT_MIN 1.175494351e-38F Valoarea pozitiva minima

FLT_MIN_10_EXP (-37) Exponentul minim in baza 10

3.4 Variabile de tip caracter


Cu toate ca tipul char este un tip intreg care are dimensiunea de 1 octet, el este folosit de obicei in mod
diferit de variabilele de tip intreg. Variabilele de tip char contin fie o valoare numerica fie un cod definit
de standardul ASCII (American Standard of Code Interchange).
Pentru a initializa variabilele cu codurile ASCII este necesar ca litera sa fie delimitata de caracterul (').
Exemplu:
char x = 'a'; // Atribuie variabilei x codul ASCII
// corespunzator literei a.

Este important de facut diferenta intre valoarea numerica si codul ASCII corespunzator unei cifre.
Urmatoarele doua variabile au valori diferite. In primul caz variabila are valoarea 5 in al doilea caz
variabila are valoarea codului asociat pentru caracterul 5 care este 53.
char x = 5; // x are valoarea 5
char y = '5'; // y are valoarea codului ASCII pentru '5' este 53.

3.4.1.1 Afisarea codurilor ASCII pe ecran


Pentru a putea afisa pe ecran valoarea codului ASCII este necesara convertirea variabilei la int. Urmatorul
exemplu afiseaza codurile ASCII pentru toate valorile posibile ale variabilelor de tip char.
1: #include <iostream>
2: using namespace std;
3:
4: int main()

17
Adonis Butufei

5: {
6: for(int i =0; i < 256; i = i + 1)
7: {
8: cout << (char) i << " " << i << "\n";
9: }
10: return 0;
11: }

Ca si contor al buclei am folosit o variabila de tip int. Pentru a putea tipari ultima valoare a intervalului
trebuia sa fixez limita la 256. Daca foloseam o variabila unsigned char intervalul posibil de valori era [0 –
255]. Atunci cand i lua valoarea 255 se executa codul buclei apoi se incrementa valoarea care in acest caz
ar fi devenit 0. In acest moment totul se repeta si obtineam o bucla infinita.

Pe linia 8 observam expresia (char)i aceasta converteste tipul variabilei i de la intreg la caracter si se
numeste castare. Vom analiza conversiile in detaliu in capitolul urmator cand vom discuta despre
operatori.

3.4.1.2 Citirea valorilor tip caracter de la tastatura


Pentru a citi valorile de tip caracter de la tastatura se foloseste functia cin. Citirea se opreste in momentul
cand am apasat tasta Enter. In cazul in care am introdus mai multe caractere, variabila va fi initializata cu
primul caracter introdus de la tastatura.
Exemplu:
#include <iostream>
using namespace std;

int main()
{
char c;
cout << "Introduceti un caracter\n";
cin >> c;

cout << "Ati introdus caracterul " << c << "\n";


return 0;
}

3.4.1.3 Categorii de coduri ASCII


Standardul ASCII s-a dezvoltat cu mult timp inainte de aparitia calculatoarelor. Din acest set nu toate
valorile se folosesc pentru reprezentarea caracterelor. Primele 32 de valori erau folosite ca si valori de
control si nu au un corespondent grafic care se afiseaza pe ecran.

Exista o categorie speciala de valori care este utilizata pentru formatarea textului. Fiecare valoare din
aceasta categorie incepe cu caracterul (\) pentru a preveni procesarea implicita a caracterului care
urmeaza. Acest grup de doua caractere se numeste secventa escape .

18
InfoAcademy Adonis Butufei

Valoare Explicatie
'\0' marcheaza sfarsitul unui sir de carcatere
'\t' insereaza un tab orizontal
'\n' muta cursorul pe linia urmatoare
'\r' muta cursorul la inceputul linei
'\"' afiseaza caracterul (")
'\\' afiseaza caracterul (\)

Valorile mai pot fi impartite logic si in alte categorii: caracterele care reprezinta cifre ('0' - '9'), litere
(majuscule, minuscule) etc. Pentru a testa apartenenta unui caracter la o categorie se folosesc functiile
declarate in fisierul <cctype>.
Tabelul de mai jos contine o scurta prezentare a acestor functii:
Functie Explicatie
isalpha(c) returneaza 1 daca c este litera mare sau mica A-Z, a-z
isupper(c) returneaza 1 daca c este litera mare A-Z
islower(c) returneaza 1 daca c este litera mica a-z
isdigit(c) returneaza 1 daca c este cifra 0-9
isxdigit(c) returneaza 1 daca c este cifra hexa 0-9,a-f,A-F
isspace(c) returneaza 1 daca c este spatiu ' ','\t','\n','\r','\f' sau '\v'
ispunct(c) returneaza 1 daca c este character de punctuatie
isalnum(c) returneaza 1 daca c este litera sau cifra
isprint(c) returneaza 1 daca c este afisabil cu spatiu
isgraph(c) returneaza 1 daca c este afisabil fara spatiu
iscntrl(c) returneaza 1 daca c este caracter de control
tolower(c) converteste caracterul c la litera mica
toupper(c) converteste caracterul c la litera mare

Urmatorul exemplu afiseaza semnele de punctuatie si codurile lor ASCII:


1: #include <iostream>

19
Adonis Butufei

2: #include <cctype>
3: using namespace std;
4:
5: int main()
6: {
7: for(int c = 0; c < 256; c = c + 1)
8: {
9: if(ispunct(c))
10: {
11: cout << c << " " << (char)c << "\n";
12: }
13: }
14:
15: return 0;
16: }

3.5 Aliasuri de tipuri


Pentru simplificarea scrierii codului in C++ putem defini aliasuri (nume secundare) altor tipuri de date
folosind operatorul typedef.
Exemple:
typedef unsigned long Ulong; // permite folosirea numelui Ulong in loc de unsigned long

3.6 Sumar
• Cea mai mica unitate de informatie este bitul.
• Un grup de 8 biti formeaza un octet.
• Variabilele se masoara in octeti.
• Pentru a determina numarul de octeti ocupati de o variabila se foloseste operatorul sizeof.
• Pe langa reprezentarea zecimala, variabiele intregi mai pot fi reprezentate in baza 8, reprezentare
octala, sau baza 16, reprezentare hexazecimala.
• Domeniul de viata al variabilelor reprezinta zona de cod in care acestea pot fi utilizate in cadrul
programului. Dupa ce sunt executate instructiunile din domeniul de viata al unei variabile, acea
variabila nu mai poate fi accesata si memoria aferenta este eliberata. Exceptie in cazul variabilelor
statice!
• Pentru a reduce cuplajul prin date este recomandabil ca variabilele sa aiba un domeniu de viata cat mai
redus.
• Calificatorul de context este utilizat pentru a accesa variabile declarate in alt fisier.
• Calificatorul de context static are doua caracteristici:
- variabilele globale statice pot fi accesate doar din fisierul curent
- variabilele locale statice sunt alocate in memorie la prima executie si valoarea lor se pastreaza pe
toata perioada rularii programului.

20
InfoAcademy Adonis Butufei

• In C++ sunt definite urmatoarele tipuri de variabile intregi: int, long si short. Primele doua tipuri ocupa
4 octeti, ultimul tip ocupa 2 octeti.
• Variabilele intregi pot avea semn sau nu. In cazul celor fara semn toate valorile sunt pozitive.
• Limitele pentru variabilele intregi sunt definite in fisierul <climits>
• Variabilele reale pot lua valori in intervale largi. Ele folosesc o reprezentare aproximativa a numerelor
datorita faptului ca au un numar finit de cifre.
• Dimensiunea variabilelor reale este de 4 sau 8 octeti.
• Pentru variabilele reale se folosesc doua notatii: zecimala si stiintifica. Cea zecimala este de forma
24.5 iar cea stiintifia este de forma 2.45 * 101 .
• Pentru testarea egalitatii variabilelor reale, datorita aproximarii, nu se poate folosi operatorul == . Se
defineste cea mai mica diferenta acceptabila. Daca diferenta celor doua numere este mai mica in
valoare absoluta decat diferenta acceptabila atunci sunt considerate egale.
• Limitele variabilelor reale sunt definite in fisierul <cfloat>.
• Tipul char foloseste codurile ASCII pentru reprezentarea informatiei ca si text.

3.7 Intrebari si exercitii


1. Care este diferenta dintre un bit si un octet?
2. Cum se poate determina numarul de octeti folosit de compilator pentru variabilele de tip double?
3. Scrieti un program care afiseaza dimensiunea variabilelor de tip bool, char, int si double.
4. Unde se foloseste reprezentare in baza 16 a numerelor intregi?
5. Care este avantajul reprezentarii in baza 16?
6. Cum se reprezinta in binar numarul 21?
7. Care este reprezentarea in hexazecimal a numarului 75?
8. Care este rezultatul urmatoarei operatii in hexazecimal: AE + 21?
9. Care este rezultatul urmatoarei operatii in hexazecimal: BD – A3?
10. Care este cea mai mare valoare care se poate reprezenta pe 32 de biti?
11. Care este diferenta dintre o variabila globala si o variabila locala?
12. Ce se intampla cu variabilele dupa ce executia programului depaseste domeniul de viata?
13. Prin ce difera o variabila statica globala de o variabila statica locala?
14. Ce este mascarea variabilelor si de ce trebuie evitata?
15. Ce se afiseaza pe ecran la rularea urmatorului program:

#include <iostream>
using namespace std;

int main()
{

21
Adonis Butufei

for(int i = 0; i < 3; i = i + 1)
{
static int a = 1;
int b = 1;

cout << "a= " << a << " b= " << b << "\n";
a = a + 1;
b = b + 1;
}

return 0;
}

16. Care este diferenta dintre o variabila de tip int si una de tip short?
17. Care este diferenta dintre o variabila cu semn si una fara semn?
18. Cum se declara o variabila fara semn de tip long long?
19. Care este valoarea variabilei dupa executarea codului:
int x = INT_MIN;
x--;

20. Cand este indeplinita conditia de iesire din bucla?


int result = 0;
for(short i = 0; i < USHRT_MAX; i = i + 1)
{
result = result + i;
}

21. Ce fisier trebuie inclus pentru a putea lucra cu limitele variabilelor de tip intreg?
22. Extindeti programul de afisare a dimensiunii variabilelor pentru toate tipurile de variabile discutate
pana acum.
23. Extindeti programul de afisare a limitelor pentru toate valorile intregi.
24. Scrieti reprezentarea zecimala pentru urmatoarele valori:
1.345e-2
45.89e-1
1234.789E-3
-324.758e-2

25. Scrieti reprezentarea stiintifica pentru urmatoarele valori astfel incat partea intreaga sa aiba 2 cifre:
234.78
0.756
-2.546

22
InfoAcademy Adonis Butufei

-2459.576
26. Modificati exemplul initial pentru compararea numerelor reale astfel incat sa foloseasca variabile de
tip float. Apar si in acest caz erorile de aproximare?
27. Ce fisier trebuie inclus pentru a folosi limitele variabilelor reale?
28. Scrieti un program care afiseaza valorile limitelor pentru variabilele de tip float si double.
29. Implementati un program care afiseaza codul ASCII si valoarea pentru toate literele si cifrele.
30. Programul urmator ruleaza in bucla infinita. Care este eroarea?
17: #include <iostream>
18: using namespace std;
19: int main()
20: {
21: for(unsigned char c = 0; c < 256; c = c + 1)
22: {
23: cout << c << " " << (int)c << "\n";
24: }
25:
26: return 0;
27: }

31. Modificati codul anterior pastrand tipul datelor, dar folosind o bucla do /while
32. Implementati o functie care primeste un caracter si daca acesta este litera o transforma in majuscula
folosind tabelul codurilor ASCII prezentat in bibliografie.

3.8 Bibliografie
• Practical C++ Programming, second edition, O'Reily, Steve Oualline, Cap 5, Cap 9.
• C++ Primer, sixth edition, Addison-Wesley Professional, Stephen Prata, Cap3.
• Reprezentarea numerelor reale http://steve.hollasch.net/cgindex/coding/ieeefloat.html
• Acuratete vs. precizie:
http://www.cprogramming.com/tutorial/floating_point/understanding_floating_point.html
• Reprezentarea double pe 64 biti: http://en.wikipedia.org/wiki/Double_precision_floating-point_format
• Codurile ASCII http://www.asciitable.com/

23

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