Sunteți pe pagina 1din 22

CAPITOLUL 6

Fundamentele limbajului C++. Partea I.


6.1. Identificatori
Identificatorii limbajului C++, ca i n limbajul C standard, sunt formai cu ajutorul caracterelor
alfanumerice i liniua de subliniere (underscore), _.
Primul caracter al unui identificator nu poate fi o cifr. De exemplu:
Raza
// valid
mesaj
// valid
_maxx // valid
a5
// valid
5a
// invalid

Din mulimea identificatorilor posibili, se remarc cuvintele cheie (reserved keywords) ale
limbajului, identificatori a cror semnificaie nu poate fi modificat de programator (Tabelul 6.1.).
Cuvintele cheie din tabel care ncep cu semnul underscor reprezint variabile interne.

6.2. Tipuri de date fundamentale


Tipul unei date determin dimensiunea zonei de memorie ocupate i valorile pe care le poate lua.
Tipurile datelor se pot grupa n tipuri fundamentale i tipuri derivate.
Tipurile de date fundamentale cuprind tipurile aritmetice de baz i tipul void.
Exist patru tipuri aritmetice de baz, specificate prin cuvintele cheie: char, int, float i double. Gama de
valori poate fi extins prin modificatori de tip desemnai prin cuvintele cheie: signed, unsigned, short,
long. Tipurile ntregi ce se obin prin combinarea tipurilor de baz cu modificatorii de tip sunt prezentate n
Tabelul 6.2., iar cele reprezentate n virgul mobil n Tabelul 6.3..
1

6.2.1. Tipul fundamental void indic absena oricrei valori i se utilizeaz n urmtoarele situaii:
declaraia unei funcii fr parametri sau care nu returneaz un rezultat, tipul pointer generic i conversii de
tip cu operatorul cast pentru pointeri.
Iat cteva exemple de expresii care returneaz ca valoare spaiul de memorie ocupat de date de diferite
tipuri:
sizeof (long int);
sizeof (unsigned char)
sizeof (long double)

// expresia returneaz valoarea 4


// expresia returneaz valoarea 1
// expresia returneaz valoarea 10

Observaie: C++ admite delimitatorii /* */ pentru inserarea de comentarii care se pot ntinde pe mai multe
rnduri i, n plus, introduce delimitatorul // pentru includerea de comentarii de sfrit de linie.
Tot textul care urmeaz dup delimitatorul // pn la sfritul liniei este considerat comentariu.
2

6.2.2. Constante
Constantele sunt valori fixe (numerice, caractere sau iruri de caractere), care nu pot fi modificate n
timpul execuiei programului. Tipul constantei este determinat de compilator pe baza valorii i sintaxei
utilizate. Ele rmn n memorie pe toat durata execuiei programului.
6.2.2.1. Constante ntregi
Tipul constantei este determinat pe baza valorii, sau prin utilizarea unui sufix (U sau u pentru unsigned,
respectiv L sau l pentru long). Constantele ntregi pot fi zecimale, octale sau hexazecimale.
Constante zecimale (baza 10)
Constantele zecimale se disting prin faptul c prima cifr este diferit de 0, cum ar fi:
23
// tip int
23u
// tip unsigned int
32768
// tip long int
77UL
// tip unsigned long int
Constante octale (baza 8)
Constantele octale sunt valori avnd prima cifr 0. Cifrele 8 i 9 sunt ilegale.
-067
// tip int
067u
// tip unsigned int
020000000 // tip long int
055ul
// tip unsigned long
089
// eroare, prima cifr indic reprezentarea n octal i numrul include cifrele 8 i 9
Constante hexazecimale (baza 16)
Constantele hexazecimale se disting prin prefixul 0x sau 0X. Pot conine cifre mai mari de 9 (af, sau
AF).
0x7FFF
// tip int
0X8000
// tip unsigned int
0xffu
// tip unsigned int
0x10000
// tip long int
0xFFul
// tip unsigned long int
6.2.2.2. Constante n virgul mobil
Constantele n virgul mobil sunt valori raionale a cror reprezentare conine n general urmtoarele
cmpuri:
parte ntreag
punct zecimal
parte fracionar
e sau E i un exponent cu semn (opional)
sufix de specificare a tipului: f sau F (foreaz tipul float) sau l sau L (foreaz tipul long double).
Se pot omite partea ntreag sau partea fracionar (dar nu amndou), punctul zecimal sau litera e (E) i
exponentul (dar nu amndou).
Tipul implicit pentru constantele n virgul mobil este tipul double.
2.1
11.22E5
-.33e-2

// valoare 2,1 (tip double)


// valoare 11,22 x 105 (tip double)
// valoare 0,33 x 10-2 (tip double)
3

.5
1.
1.f
0.L

// valoare 0,5 (tip double)


// valoare 1 (tip double)
// valoare 1 (tip float)
// valoare 0 (tip long double)

6.2.2.3. Constante caracter


Constantele caracter sunt reprezentate de unul sau mai multe caractere ncadrate de apostrofuri, de
exemplu: a,A,\n i ele sunt de tip char.
Pentru a specifica o serie de caractere neafiabile, delimitatorii (), (), caracterul (\), etc. se
utilizeaz secvenele escape (secvene de evitare) (vezi Tabelul 6.4.).

Exemple de utilizare a constantelor caracter:


#include <stdio.h>
void main()
{
putch(?);
putch(63);
printf(\n%c,\077);
printf(\n%c,\x3F);
}

// se afieaz caracterul ?
// se afieaz caracterul ?, 63 fiind valoarea corespunztoare n codul ASCII
// se afieaz caracterul ?
// se afieaz caracterul ?

Observaie: n C, toate constantele de un singur caracter au tipul int i sunt reprezentate intern pe 16 bii cu
octetul mai semnificativ 0 pentru valoarea caracterului mai mic dect 128, sau 1 (0xFF) pentru valori n
intervalul 128255.

6.2.2.4. Constante caracter duble (specifice pentru C++)


Limbajul C++ permite specificarea unor constante alctuite din dou caractere, reprezentate pe 16 bii (tipul
int) ca n exemplul care urmeaz:
ab
\t\t

// reprezentarea n memorie ca ntreg de valoare 25185 (0x62 0x61)


// reprezentarea n memorie ca ntreg de valoare 2313 (0x09 0x09)

Primul caracter este memorat n octetul mai puin semnificativ.


Observaie: Constantele duble pot ridica probleme de portabilitate, ele nefiind
recunoscute de alte compilatoare.
6.2.2.5. Constante iruri de caractere
Constantele iruri de caractere sunt alctuite dintr-un numr oarecare de caractere, ncadrate ntre ghilimele.
irurile de caractere se memoreaz n tablouri de tipul char, cu dimensiune egal cu numrul de caractere
cuprinse ntre ghilimele, la care se adaug terminatorul de ir \0.
Exemplu de constanta sir de caractere
Caracterele ce alctuiesc irul pot fi secvene escape:
\tMesaj 1\n\tMesaj 2
irurile constante adiacente se concateneaz i formeaz un singur ir:
Programare orientata pe obiecte
Pentru scrierea irurilor lungi se poate utiliza simbolul (\) care semnaleaz continuarea irului pe rndul
urmtor:
Exemplu de sir \
scris pe doua randuri
6.2.3. Variabile
6.2.3.1. Declaraii de variabile
Toate variabilele trebuie declarate nainte de a fi folosite.
Declaraia unei variabile (obiect) precizeaz numele (identificatorul) cu care va fi referit, cruia i poate
asocia o serie de atribute, cum ar fi:
- tipul datei poate fi tip fundamental sau definit de utilizator i determin structura, gama de valori,
dimensiunea spaiului ocupat n memorie;
- clasa de memorare stabilete zona de memorie n care se va plasa informaia asociat identificatorului
(segment de date, registru, stiv, heap) i delimiteaz durata sa de alocare;
- domeniul reprezint poriunea de program n care poate fi accesat informaia asociat identificatorului,
el fiind determinat de poziia declaraiei;
- durata de via a identificatorului reprezint perioada ct exist efectiv n memorie i este corelat cu
clasa de memorie;
5

- legtura precizeaz modul de asociere a unui identificator cu un anumit obiect sau funcie, n procesul de
editare a legturilor.
Atributele se pot asocia identificatorilor n mod implicit, n funcie de poziia i sintaxa declaraiei sau
explicit prin utilizarea unor specificatori.
Sintaxa unei declaraii de variabil impune specificarea tipului, avnd forma general:
tip_var nume_var;
tip_var este un specificator de tip de date oarecare, standard, pointer sau definit de utilizator.
// declararea variabilei r de tip pointer la float,
// declararea variabilei n de tip unsigned int

float * r;
unsigned int n;

Se pot face declaraii de variabile cu iniializare utiliznd sintaxa:


tip_var nume_var= valoare_initiala;
sau se pot declara mai multe variabile de acelai tip utiliznd sintaxa:
tip_var nume_var1<=val_initiala1>,< nume_var2<= val_initiala2>>,...;
double real=2.5; // declararea variabilei real de tip double, iniializat cu valoarea 2.5
char c1, c2=a, ch;
// declararea a trei variabile de tip char, c1, c2 i ch, variabila c2

// fiind iniializat cu valoarea a


Poziia declaraiei determin cele dou domenii de existen fundamentale:
- Domeniul bloc (local)
Identificatorii cu domeniu bloc se numesc locali i sunt rezultatul unor declaraii n interiorul unui bloc (au
domeniul cuprins ntre declaraie i sfritul blocului) sau sunt parametrii formali din definiia unei funcii
(au ca domeniu blocul funciei).
- Domeniul fiier (global)
Identificatorii cu domeniu fiier se numesc globali i sunt declarai n afara oricror funcii (domeniul este
cuprins ntre declaraie i sfritul fiierului).
#include <stdio.h>

// zona declaraiilor globale


int functie (int, float);
// se declar variabila cu numele a, creia i se rezerv o zon de memorie de 2
int a;

// octei (16 bii) localizat n segmentul de date, deoarece declaraia se afl n


// zona declaraiilor globale definiii de funcii
void main (void)
{
unsigned char c;
float r=2.5;

// se declar variabila automatic cu numele c creia i se rezerv un


// octet n segmentul de stiv, variabila fiind o variabil local
// se declar variabila automatic cu numele r creia i se rezerv 4
// octei n segmentul de stiv, variabila fiind o variabil local care este
// iniializat cu valoarea 2.5

}
int functie (int n, float q)

// se declar variabilele locale n i q, crora li se aloc 2,


// respectiv 4 octei n segmentul de stiv

}
6

Observaii:
1. ntr-un bloc inclus n domeniul unei declaraii este permis o declaraie local a aceluiai identificator,
asocierea fiind ns fcut unui alt obiect cu alocarea altei zone de memorie.
2. Spre deosebire de C, care impune gruparea declaraiilor locale la nceputul unui bloc, C++ permite
plasarea declaraiilor n interiorul blocului, bineneles nainte de utilizarea obiectului.
void main (void)
{

for (int i=5; i<8; i++)


{}
for {i=0; i<5; i++)

// declararea lui i este imediat urmat de utilizarea sa

// i a fost declarat anterior


{}

}
Clasa de memorare se poate preciza prin specificatorii auto, static, extern, register. Aceti specificatori
precizeaz modul de alocare a memoriei i timpul de via pentru variabile i legtur pentru funcii i
variabile.
auto
Declaraia auto specific o variabil automatic i se poate utiliza pentru variabile cu domeniul local (cu
spaiu alocat pe stiv). Variabilele ce se declar n interiorul unui bloc sunt implicit automatice, astfel c
declaraia auto este rar folosit.
void fct()
{
auto float r;
double s;

// declararea unei variabile automatice cu declarare explicit


// declararea unei variabile implicit automatic

...
}
static
Declaraia static a unei variabile locale foreaz durata static fr a modifica domeniul de existen.
Variabilele statice i pstreaz valoarea ntre dou apeluri succesive ale blocurilor care le conin,
asigurndu-se n acelai timp o protecie, dar ele nu pot s fie accesate din blocuri care nu constituie
domeniul lor de existen. Variabilele statice pot fi declarate cu iniializare, n caz contrar, implicit se
iniializeaz cu valoarea 0, similar variabilelor globale.
#include <stdio.h>
int fct()
{
// se declar o variabil local funciei, cu durat static
static int a=2;
return (a++); }
void main(void)
{
int n;
n=fct();
printf (\n Prima atribuire : n= %d, n);
n=fct();
printf (\n A doua atribuire : n= %d, n);
}

Programul afieaz:
Prima atribuire : n= 3 (la primul apel al funciei, variabila a are valoarea iniial 2, ea fiind apoi
incrementat ).
A doua atribuire : n= 4 (la al doilea apel al funciei, variabila a are la nceput valoarea 3, valoare datorat
apelului anterior al funciei, valoarea fiind apoi incrementat.
register
Declaraia register are ca efect memorarea variabilei ntr-un registru al procesorului i nu n memorie,
avnd ca rezultat creterea vitezei de execuie a programului. Aceste variabilele pot fi variabile locale,
nestatice, de tip int sau char. Numai dou variabile pot fi memorate simultan n registre, n cazul existenei
mai multor declaraii register, cele care nu pot fi onorate vor fi tratate
de compilator ca variabile obinuite.
register char c;

// declararea variabilei c cu memorare ntr-un registru al procesorului

extern
Specificatorul extern indic legtura extern i asigur durata static pentru variabile locale i globale sau
pentru funcii (acestea au implicit legtur extern i durat static).
Pentru identificatorii cu legtur extern sunt permise mai multe declaraii de referin, dar o singur
definiie. De exemplu, n cazul unui proiect n care o variabil se folosete n mai multe fiiere, ea se va
defini global ntr-un fiier, n celelalte fiind declarat extern fr definire. Compilatorul i va aloca o
singur dat memorie.
// Fiier Ex_prj.cpp
#include <stdio.h>

extern int m; // se declar legtur extern pentru variabila m


void main(void)
{

scanf(%d, &m);
printf(\nm= %#x, m);

}
// Fiier Ex_prj1.cpp
...
int m ;
// declaraia variabilei m

n exemplul anterior, cele dou fiiere, Ex_prj.cpp i Ex_prj1.cpp, se includ ntr-un proiect utiliznd
opiunea project a meniului principal din mediul de programare C/C++. Variabila m este declarat global
ntr-unul dintre fiiere, ea putnd fi referit din cellalt fiier datorit specificrii legturii extern .

6.2.3.2. Modificatori de acces


Modificatorii de acces ce pot fi utilizai sunt const i volatile i ei pot controla modul de modificare a unei
variabile.
const
Variabilele const nu pot fi modificate pe parcursul execuiei unui program. Instruciunile care ncearc
modificarea variabilelor const genereaz erori la compilare.
8

const int a=99;


a++;
a+=5;

// declaraia variabilei a const


// eroare, a este const
// eroare, a este const

O variabil pointer constant nu se poate modifica, n schimb se poate modifica obiectul indicat.
n cazul unui pointer ctre un obiect constant, valoarea pointerului este modificabil, dar nu i valoarea
obiectului.
void main()
{
int var1=25, var2=44;
const int var3=7;
int * p1=&var1;
int * p2=&var3;
const int * p3=&var3;
var3++;
*p3=15;
int * const p4=&var1;
p4=&var2;
*p4++;

// declaraie cu iniializare
// eroare, nu se poate converti const int * la int *
// corect, tipul de date corespund
// eroare, se ncearc modificarea unui obiect constant
// eroare, se ncearc modificarea unui obiect constant
// corect, se declar un pointer constant
// eroare, se ncearc modificarea unui pointer constant
// corect, se modific valoarea obiectului var2 care nu
// este declarat constant

}
n mod uzual se folosesc funcii cu parametri pointeri ctre obiecte constante atunci cnd se dorete
protejarea la modificare a acestora.
Un exemplu este o funcie care realizeaz criptarea unui ir de caractere:
#include <stdio.h>
#include <string.h>
void criptare(const char *sir_i, char *sir_c);

// parametrul sir_i este declarat const pentru a


// evita modificarea lui n interiorul funciei
// criptare()

void main()
{
char sir_initial[80], sir_criptat[80];
sir_initial=Exemplu criptare;
criptare(sir_initial, sir_criptat);
printf(\nSirul criptat este: %s, sir_criptat);
}
void criptare( const char *sir_i, char *sir_c)
{
while (*sir_i)
{
// criptarea se face prin modificarea codului ASCII
*sir_c = * sir_i+1 ;
sir_i ++ ;
sir_c ++ ;
}
*sir_c=\0;
}

volatile
Variabilele volatile pot fi modificate din exteriorul programului (de exemplu servirea unei ntreruperi).
6.2.4. Declaraia typedef
Specificatorul typedef nu declar un obiect, ci asociaz un nume unui tip de date. Sintaxa este:
typedef tip_data identificator_tip
typedef unsigned char octet;
octet var;

// tipul unsigned char este echivalent cu octet


// variabila var se declar de tip octet

6.2.4.1. Tipuri de date derivate


Pointeri de date
Tipul pointer (indicator) reprezint adrese ale unor zone de memorie (adrese de variabile sau constante).
Exist, de asemenea, pointeri generici, numii pointeri void, care pot conine adresa unui obiect de orice tip.
Declararea variabilelor pointer
Sintaxa declaraiei unui pointer de date este:
tip * id_ptr;
Simbolul * precizeaz c id_ptr este numele unei variabile pointer, iar tip este tipul obiectelor a cror
adres o va conine (tipul de baz al id_ptr).
Compilatorul interpreteaz zona de memorie adresat de pointer ca obiect de tipul indicat in declaraie, cu
toate atributele tipului: dimensiunea zonei de memorie necesar i semnificaia informaiei coninute.
Declararea unui pointer generic se face folosind sintaxa:
void * id_vptr;
n cazul acestei declaraii, dimensiunea zonei de memorie adresate i interpretarea informaiei nu sunt
definite, iar proprietile difer de ale celorlali pointeri de obiecte.
int * ptr;
int * tabptr[10];
float **pptr;

// pointer la ntreg
// tablou de pointeri ctre ntregi
// dubl indirectare; pointer la pointer

Este important c orice variabil pointer trebuie iniializat cu o valoare valid, 0 (NULL) sau adresa unui
obiect nainte de a fi utilizat. In caz contrar, efectele pot fi grave deoarece la compilare sau n timpul
execuiei nu se fac verificri ale validitii valorilor pointerilor.
Operatori specifici.
Exist doi operatori unari care permit folosirea variabilelor pointer:
operatorul & se folosete pentru aflarea adresei unei variabile oarecare i
operatorul * pentru accesul la variabila adresat de un pointer.

#include <stdio.h>
void main(void)
{
int var=20, *pvar;
printf("\nVariabila var se afla la adresa %p, &var);
printf("si are valoarea var= %d", var);
pvar=&var;
printf("\nVariabila pvar are valoarea %p, pvar);
printf("si adreseaza obiectul: %d", *iptr);

10

*iptr=50;
printf("\nNoua valoare a lui var este %d, var);
}

Programul afieaz:
Variabila var se afl la adresa: FFF4 si are valoarea iv= 20
Variabila pvar are valoarea: FFF4 si adreseaza obiectul: 20
Noua valoare a lui var este 50
Situaia:
tipl * id_pl;
tip2 * id_p2;
id_pl=&id_p2;
nu genereaz erori dac tip1 i tip2 sunt identice, sau, n caz contrar dac tip1 este void.
Dac se folosete un pointer void, pentru orice referire a obiectului adresat este necesar precizarea
explicit a tipului utiliznd operatorul cast.
void main()
{ void *p1;
float *p2, var=1.5;
p2=&var;
p1=p2;
printf(\nValoarea referita de p1: %f , * (float *) p1);
}

6.2.4.2. Variabile referin


C++ ofer posibilitatea de a declara identificatori ca referine de obiecte (variabile sau constante).
Referinele, ca i pointerii, conin adrese. Pentru a declara o referin la un obiect se folosete simbolul &,
folosind sintaxa:
tip & id_referinta = nume_obiect;
tip este tipul obiectului pentru care se declar referina, iar simbolul & precizeaz c id_referinta este
numele unei variabile referin, iar nume_obiect este obiectul a crui adres va fi coninut n id_referinta.
int n;
int * p=&n;
int &r=n;
n=20;
*p=25;
r=30;

// se declar n de tip ntreg


// se declar pointerul p cu iniializare adresa lui n
// se definete r referina lui n
// n primete valoarea 20
// n primete valoarea 25
// n primete valoarea 30

n exemplul anterior, att p, ct i r, acioneaz asupra variabilei n. Atunci cnd se acceseaz o variabil
prin referina sa, nu este necesar s se foloseasc adresa, acest lucru realizndu-se automat.
Spre deosebire de pointeri, care la un moment dat pot primi ca valoare adresa unei alte variabile, referinele
nu pot fi modificate, ele fiind practic o redenumire a variabilei a cror adres o conin (se creeaz un alias
al respectivei variabile).
n utilizarea referinelor, trebuie avute n vedere urmtoarele restricii:
referinele trebuie iniializate n momentul declarrii;
referinelor nu li se pot modifica locaiile la care se refer;
11

nu sunt permise referine la cmpuri de bii, referine la referine i pointeri la referine, deci nici
tablouri de referine.

int &r ;
// eroare, se declar o referin fr iniializare
int &r=20 ;
// corect, se declar o referin la o constant
const int i = 20;
// eroare, se declar o referin ntreag la o constant ntreag
int &r = i ;
const int i = 20;
const int &r = i ; // corect, se declar o referin constant ntreag la o constant ntreag

Observaie: Referinele de sine stttoare sunt rar folosite. n schimb, utilizarea parametrilor formali
referin permite transferul prin referin simplu i eficient, fr recurgerea la parametri formali pointeri.
6.2.4.3. Tablouri de date
Tabloul de date (sau masiv de date) este o colecie de date de acelai tip, plasate ntr-o zon
contigu de memorie.
Sintaxa declaraiei unui tablou cu N dimensiuni este:
tip_element nume_tablou [dimensiune1][dimensiune2][dimensiuneN]
Zona de memorie rezervat conine dimensiune1 x dimensiune2 x...x dimensiuneN elemente de tipul
tip_element.
Referirea unui element de tablou se face cu operatorul de indexare [ ] sub forma:
nume_tablou [indice1][indice2]...[indiceN]
Declaraia unui tablou se poate face cu iniializarea sa folosind sintaxa:
declaratie_tablou={list_valori};
Lista de valori trebuie s conin constante de tip compatibil cu tipul de baz al tabloului, n ordinea plasrii
n memorie.
float vect1[5];
// se declar un tablou cu 5 elemente float, fr iniializare
vect1[0]=1.5;
// elementului de index 0 i se atribuie valoarea 1.5
int vect2[10]={2,7,-1,0,9,15,-5,22,6,11};
// se declar un tablou cu 10 elemente int cu

// iniializare
// se declar un tablou bidimensional cu 2*3
// elemente de tip ntreg, cu iniializare
mat[1][2]= 23;
// elementului de indeci 1, respectiv 2, i se atribuie valoarea 23
Tablourile unidimensionale cu elemente de tip char sunt folosite pentru memorarea irurilor de caractere.
Pentru a marca sfritul unui ir de caractere, dup ultimul caracter se adaug un octet cu valoarea 0 (\0),
numit i terminator de ir.
int mat[2][3]={{3,5,-3},{2,-1,0}};

// se declar un tablou unidimensional, cu elemente char (ir de caractere), fr


// iniializare
char sir3[ ]=sir de caractere;
// se declar un tablou cu 17 elemente char (ir de
// caractere) cu iniializare (ultimul caracter depus n
// tablou este terminatorul de ir \0
sir3[0]=S;
// primul caracter al irului primete valoarea S
char sir1[10];

Numele unui tablou fr index este un pointer constant de tipul elementelor tabloului i are ca valoare
adresa primului element al tabloului.
12

float tab[20], *ptr;


ptr=tab;

// atribuire valid, pointerul ptr va conine adresa primului element al


// tabloului

&tab[0] = = tab ;
&tab[2] = = tab+2 ;
tab[0] = = *tab ;
tab[2] = = *(tab+2) ;
tab++ ;
// eroare, tab este un pointer constant, deci nu se poate incrementa
ptr++ ;

// corect, ptr este un pointer la float, nu a fost declarat constant

Tablourile multidimensionale reprezint tablouri cu elemente tablouri, astfel nct numele tabloului (fr
index) este un pointer de tablouri.
float mat[10][10];
float *p;
p=mat;
p=(float*)mat;
mat = = &mat[0][0];
mat+1 = = &mat[1][0];
*(mat+9) = = mat[9][0];

// mat reprezint un tablou de pointeri float


// p este un pointer float
// eroare, tipurile pointerilor difer
// corect, s-a folosit o conversie explicit de tip
// expresie adevrat
// expresie adevrat
// expresie adevrat

6.2.4.4. Tipuri de date definite de utilizator


Tipurile de date fundamentale i derivate nu pot acoperi totdeauna necesitile de organizare a
informaiei, n numeroase situaii fiind necesar asocierea de date de tipuri diferite.
Vom prezenta n continuare posibilitile oferite de limbajul C pentru definirea unor tipuri de date cu un
grad de complexitate sporit. Acestea sunt:
- enumerarea, care este o list de identificatori cu valori constante de tip ntreg;
- structura, care este o colecie de date de tipuri diferite referite cu acelai nume;
- cmpul de bii, care este un membru al unei structuri cruia i se aloc n memorie un numr de bii n
interiorul unui cuvnt;
- uniunea, care permite utilizarea aceleiai zone de memorie de obiecte de tipuri diferite.
Noiunile puse n discuie n aceast lucrare de laborator sunt cele comune celor dou limbaje, urmnd ca,
ntr-o lucrare ulterioar tratarea acestora s se completeze cu aspecte specifice limbajului C++.
6.2.4.4.1. Enumerarea
Tipul enumerare const dintr-un ansamblu de constante ntregi, fiecare asociat unui identificator.
Sintaxa declaraiei este:
enum <id_tip_enum> {id_elem<=const>,} <lista_id_var>;
unde: id_tip_enum = nume tip enumerare;
id_elem = nume element;
const = constant de iniializare a elementului.
Dac declaraia nu specific o constant, valorile implice sunt 0 pentru primul element, iar pentru celelalte
valoarea elementului precedent incrementat cu o unitate.
Identificatorii elementelor trebuie s fie unici n domeniul lor (diferii de numele oricrei variabile, funcie
sau tip declarat cu typedef).
13

enum boolean {false, true};

// valoarea identificatorului false este 0, iar a lui true este 1

sau
typedef enum {false, true} boolean; // declaraia este echivalent declaraiei anterioare
# include <stdio.h>
// valoarea identificatorului false este 0, iar a lui true este 1
enum boolean {false, true};
void main()
{
boolean op1=false, op2;
op2=true;
printf(\n op1=%d\nop2=%d, op1, op2);
}

Tipul enumerare faciliteaz operarea cu variabile care pot lua un numr mic de valori ntregi, asociindu-se
nume sugestive pentru fiecare valoare.
Programul devine mai clar i mai uor de urmrit.
6.2.4.4.2. Structuri
Structura este o colecie de date referite cu un nume comun. O declaraie de structur precizeaz
identificatorii i tipurile elementelor componente i constituie o definiie a unui nou tip de date.
Sintaxa declaraiei unui tip structur este:
struct id_tip_struct {
tip_elem1 id_elem1;
tip_elem2 id_elem2;

tip_elemN id_elemN;} lista_id_var_struct;


unde: struct = cuvnt cheie pentru declararea tipurilor structur;
id_tip_struct = numele tipului structur declarat;
tip_elemK = tipul elementului K, unde K=1N;
id_elemK = numele elementului K;
lista_id_var_struct = lista cu numele variabilelor de tipul declarat,
id_ti_struct.
Pot s lipseasc, fie numele structurii, fie lista variabilelor declarate, dar nu amndou. De regul se
specific numele tipului structur definit, aceasta permind declaraii ulterioare de obiecte din acest tip.
struct data
{
unsigned int zi;
unsigned int luna;
unsigned int an;
};
struct persoana
{
char nume[15];
char prenume[15];
data data_n;
} pers1, pers2;

// se declar tipul de date data, ca structur cu 3 membri de tip unsigned int

// se declar tipul de date persoana ca structur cu 2


// membri ir de caractere i un membru de tip data

// odat cu declaraia tipului de date persoana, se declar


// dou obiecte din acest tip de date
14

Se poate declara un tip structur cu ajutorul declaraiei typedef cu sintaxa:


typedef struct {
tip_elem1 id_elem1;
tip_elem2 id_elem2;

tip_elemN id_elemN;} id_tip_struct;


unde semnificaia denumirilor este identic cu cea anterioar.
Se reia exemplul anterior, utiliznd typedef pentru declaraia structurilor:
typedef struct
{
unsigned int zi;
unsigned int luna;
unsigned int an;
} data;
typedef struct
{
char nume[15];
char prenume[15];
data data_n;
} persoana;

Elementele structurii se numesc generic membrii (cmpurile) structurii.


Tipurile membrilor pot fi oarecare, mai puin tipul structur care se definete, dar pot fi de tip pointer la
structura respectiv.
Iniializarea unei variabile structur se face prin enumerarea valorilor membrilor n ordinea n care apar n
declaraie.
persoana pers={Ionescu, Adrian, 10, 10, 1975};
// declararea unui obiect persoana
// cu iniializare
Referirea unui membru al unei variabile de tip structur se face folosind operatorul de selecie (.) (punct),
sub forma:
nume_variabil . nume_cmp
printf(\nNumele: %s, pers.nume);
printf(\nPrenume: %s, pers.prenume);
printf(\nData nasterii: %d.%d.%d, pers.data_n.zi, pers.data_n.luna, pers.data_n.an);

Referirea unui membru al unei structuri indicate de un pointer se face folosind operatorul de selecie
indirect (->) (sgeat).
persoana * p_pers;
// se declar un obiect pointer la persoana
puts(\nIntroduceti numele:);
scanf(%s, &p_pers->nume);
puts( \nIntroduceti prenumele:)
scanf(%s, &p_pers->prenume);
puts( \nIntroduceti data nasterii:);
scanf(%d.%d.%d, &p_pers->data_n.zi, &p_pers->data_n.luna, &p_pers->data_n.an);

Operatorul de atribuire admite ca operanzi variabile structur de acelai tip, efectund toate atribuirile
membru cu membru.
persoana p1={Popescu, George, 5, 12, 1982}, p2; // p1 se declar cu iniializare
// prin atribuire, p2 preia, membru cu membru datele din p1
p2=p1;

15

printf(\nNumele:%s, p2.nume);
printf(\nPrenume:%s, p2.prenume;
printf(\nData nasterii: %d.%d.%d, p2.data_n.zi, p2.data_n.luna, p2.data_n.an);

Transferul unui parametru de tip structur se poate face prin valoare.


Parametrul formal i cel efectiv trebuie s fie de acelai tip.
#include <stdio.h>
typedef struct complex {int re, im;} ;
complex suma(complex a, complex b)
{
complex c;
c.re=a.re+b.re;
c.im=a.im+b.im;
return c;
}
void main()
{
complex c1, c2, c3;
scanf("%d", &c1.re);
scanf("%d", &c1.im);
scanf("%d", &c2.re);
scanf("%d", &c2.im);
c3=suma(c1, c2);
printf("\n%i %i", c3.re, c3.im);
}

Transferul unui parametru de tip structur se poate face prin referin.


Parametrii efectivi trebuie s fie adrese de structuri de acelai tip cu parametrii.

#include <stdio.h>
typedef struct complex {int re, im;} ;
complex suma(complex *a, complex *b)
{
complex c;
c.re=a->re+b->re;
c.im=a->im+b->im;
return c;
}
void main()
{
complex c1, c2, c3;
c1.re=12;
c1.im=-7;
c2.re=29;
c2.im=35;
c3=suma(&c1, &c2);
printf("\n%i %i", c3.re, c3.im);
}

Pentru transferul parametrilor de tip structur se pot folosi variabile referin de structur de acelai tip.

16

include <stdio.h>
typedef struct complex {int re, im;} ;
complex suma(complex &a, complex &b)
{
complex c;
c.re=a.re+b.re;
c.im=a.im+b.im;
return c;
}
void main()
{
complex c1, c2, c3;
puts(\nIntroduceti valorile:
scanf(%d, &c1.re);
scanf(%d, &c1.im);
scanf(%d, &c2.re);
scanf(%d, &c2.im);
c3 = suma(c1,c2);
printf(\nc3=%d + i* %d", c3.re, c3.im);
}

6.2.4.4.3. Cmpuri de bii


Cmpul de bii este un membru al unei structuri sau uniuni care are alocat un grup de bii n
interiorul unui cuvnt de memorie. Declaraia unei structuri cu membrii cmpuri de bii se face sub forma:
struct id_tip_struct
{
tip_elem1 id_elem1 : lungime;
tip_elem2 id_elem2 : lungime;

tip_elemN id_elemN : lungime;


} lista_id_var_struct;
unde lungime reprezint numrul de bii utilizai pentru reprezentarea n memorie a cmpului respectiv.
Restriciile care se impun la declararea cmpurilor de bii sunt:
tipul poate fi int signed sau unsigned;
lungimea este o constant ntreag cu valoarea n domeniul 0-15;
nu se poate evalua adresa cmpului, deci nu se poate folosi operatorul & pentru acel cmp;
nu se pot folosi tablouri de cmpuri de bii.
Referirea membrilor se face ca pentru orice structur, folosind operatorii de selecie direct sau indirect
(punct sau sgeat).
#include <stdio.h>
typedef struct
{
//
unsigned int zi:5;
unsigned int luna:4;
//
unsigned int an:11;
//
} DATE;
void main()
{
//
DATE data_n;
unsigned int aux1, aux2, aux3;
puts(Introduceti data :)

se declar membrul zi cu reprezentare pe 5 bii


se declar membrul luna cu reprezentare pe 4 bii
se declar membrul an cu reprezentare pe 11 bii

se declar un obiect de tip DATE


17

scanf(%2d.%2d.%4d, &aux1, &aux2, &aux3); // este necesar utilizarea unor variabile

// auxiliare pentru citirea valorilor, deoarece pentru cmpurile de bii nu se


// poate face referire la adres
data_n.zi=aux1;
data_n.luna=aux2;
data_n.an=aux3;
....}

Se poate observa c zona de memorie ocupat de un obiect date este de 3 octei, spre deosebire de structura
care nu include cmpuri de bii care ocup 6 octei.
printf(data_n ocupa %d octeti, sizeof(data_n));
6.2.4.4.4. Uniuni
Uniunea permite utilizarea n comun a unei zone de memorie de ctre mai multe obiecte de tipuri
diferite. Sintaxa de declarare a unei uniuni este similar declaraiei unei structuri:
union id_tip_uniune {
tip_elem1 id_elem1;
tip_elem2 id_elem2;

tip_elemN id_elemN;} lista_id_var_uniune;


sau
typedef union {
tip_elem1 id_elem1;
tip_elem2 id_elem2;

tip_elemN id_elemN;} id_tip_uniune;


Spaiul alocat n memorie corespunde tipului de dimensiune maxim, membrii uniunii utiliznd n comun
zona de memorie.
#include <stdio.h>
struct octet
{
unsigned int b0:1;
unsigned int b1:1;
unsigned int b2:1;
unsigned int b3:1;
unsigned int b4:1;
unsigned int b5:1;
unsigned int b6:1;
unsigned int b7:1;
};
union intreg
{
char val;
octet bit;

// se declar o structur care ocup un octet de memorie,


// cu acces separat, prin membrii si, la fiecare bit n parte

// se declar o uniune ce ocup un octet de memorie care poate


// fi accesat ca i char prin membrul val, sau ca octet prin membrul bit

};

18

void main ()
{
intreg i;
i.val=22;

// se afieaz fiecare bit al uniunii separat:


printf("\n0x%x se reprezinta in binar: %d%d%d%d%d%d%d%d", i.val, i.bit.b7,
i.bit.b6, i.bit.b5, i.bit.b4, i.bit.b3, i.bit.b2, i.bit.b1, i.bit.b0);
}

Programul afieaz:
0x16 se reprezinta in binar 00010110
6.3. Operaii de intrare / ieire cu consola
C++ permite utilizarea funciilor de intrare/ieire C, ns dispune de un sistem de intrare/ieire conceput
n spiritul POO, mai flexibil i mai comod.
n C++ sunt predefinite dispozitive logice de intrare/ieire standard similare celor din limbajul C:
cin = console input = dispozitiv de intrare consol, tastatura (echivalent cu stdin din C);
cout = console output = dispozitiv de ieire consol, monitorul (echivalent cu stdout din C).
cerr = dispozitiv de ieire pentru afiarea erorilor, fr memorare (echivalent cu stderr din C).
clog = dispozitiv de ieire pentru afiarea erorilor, cu memorare (nu are echivalent n C).
Transferul informaiei cu formatare este efectuat de operatorul >> pentru intrare (de la cin) i de <<
pentru ieire (ctre cout), deci:
cin >> var;
cout << var;

/* citete var de la cin */


/* scrie var la cout */

Sunt posibile operaii multiple, de tipul:


cin >> var1 >> var2 ... >> varN;
cout << var1 << var2 ... << varN;
n acest caz, se efectueaz succesiv, de la stnga la dreapta, scrierea la cout, respectiv citirea de la cin a
valorilor varl ... varN.
Tipurile datelor transferate ctre cout pot fi:
toate tipurile aritmetice;
iruri de caractere;
pointeri de orice tip n afar de char.
Tipurile datelor citite de la cin pot fi:
toate tipurile aritmetice;
iruri de caractere.
Controlul formatului pentru ambele operaii este posibil, dar nu este obligatoriu deoarece exist formate
standard. Acestea sunt satisfctoare pentru dialogul cu consola efectuat n exemplele din capitolele
urmtoare.
19

Pentru citirea/scrierea irurilor de caractere se poate specifica o constant ir sau un pointer de caractere.
Din acest motiv, pentru afiarea adresei unui ir este necesara o conversie explicit la pointer de alt tip, de
exemplu (void *).
Valorile adreselor se afieaz n hexazecimal.
Operaiile de citire de la tastatur efectuate cu operatorul >> sunt similar cu cele efectuate cu scanf().
Delimitatorii cmpurilor introduse sunt spaiu, tab, linie noua, etc. In cazul citirii unui caracter nevalid,
citirea este ntrerupt i caracterul rmne n tamponul de intrare genernd probleme similare cu cele care
apar la utilizarea funciei scanf0.
Utilizarea dispozitivelor i operatorilor de intrare/ieire C++ impune includerea fiierului antet
iostrearm.h. Exemplul urmtor este elocvent pentru elegana i simplitatea dialogului cu consola n C++.
#include <iostream.h>
void main()
{
int i;
char nume[21];
float r;
cout < < "introduceti un numar intreg si apoi un numar real: ;
cin>>i >> r;
cout << "\nAti introdus: "<< i << "si" << r <<'\n';
cout << "Introduceti numele dvs: ;
cin >> nume;
cout<<"Salut, " < < nume << " !\n ;
}

Programul afieaz:
Intruduceti un numar intreg si apoi un numar real:15 3.1416
Ati introdus:15 si 3.1416
Introduceti numele dvs: ANDREI
Salut, ANDREI !
Pentru afiare se pot utiliza expresii:
#include <iostream.h>
int main() {
int num;
cin >> num;
cout << num + 1; }

// se afieaz rezultatul returnat de expresia num+1

Pentru citirea/scrierea irurilor de caractere se poate specifica o constant ir sau un pointer de caractere.
Din acest motiv, pentru afiarea adresei unui ir este necesar o conversie explicit la pointer de alt tip, de
exemplu (void *).
Valorile adreselor se afieaz n hexazecimal.
#include <iostream.h>
void main()
{
char sir[20]=Sir de caractere; // se declar un ir de caractere cu iniializare
cout<<sir<<\n;
// se afieaz coninutul sirului de caractere sir

20

cout<<*sir<<\n;
cout<<&sir<<\n;
cout<<(void*)sir<<\n;
cin>>*sir;
cout<<sir<<\n;
cin>>sir;
cout<<sir<<\n;
char * p_sir=abc;

// se afieaz primul caracter din irul de caractere sir


// se afieaz adresa la care se afl variabila pointer sir
// se afieaz adresa la care se afl variabila pointer sir
// se citete un alt caracter pentru prima poziie a irului
// se afieaz coninutul irului de caractere sir
// se citete o nou valoare pentru irul de caractere
// se afieaz coninutul irului de caractere sir
// declar un pointer la tipul char ce se iniializeaz cu

// adresa irului constant abc


cout<<p_sir<<\n;

// se afieaz coninutul irului de caractere ctre care

// pointeaz p_sir
// se afieaz primul caracter din irul constant de caractere
// se afieaz adresa la care se afl variabila pointer p_sir
// se afieaz adresa coninut de variabila pointer p_sir,
// deci adresa la care se afl irul constant abc
}
cout<<*p_sir<<\n;
cout<<&p_sir<<\n;
cout<<(void*)p_sir<<\n;

Programul afieaz:
Sir de caractere
S
0xffe0
0xffe0
s
sir de caractere
Alt sir de caractere
Alt sir de caractere
abc
a
0xfff4
0x00be

//caracterul introdus de la tastatur


// irul introdus de la tastatur

Concatenarea irurilor de caractere la afiare se poate realiza ca n exemplul urmtor:


#include <iostream.h>
int main()
{
cout << "Acesta este un sir prea lung "
"pentru a fi scris pe un singur rand.\n"
"El poate fi continuat pe randul urmator.\n"
}

Programul afieaz:
Acesta este un sir prea lung pentru a fi scris pe un singur rand.
El poate fi continuat pe randul urmator.
Observaie: Trebuie reinut c operatorii >> i << i pstreaz i semnificaia din C - operatori de
deplasare bit cu bit la dreapta, respectiv la stnga.
21

Pentru formatarea intrrilor i ieirilor sunt definii o serie de manipulatori. De exemplu, ntregii pot fi
nsoii de dec, oct, hex, pentru reprezentarea n zecimal, octal, respectiv hexazecimal. Valoarea implicit
este dec. De asemenea, se poate folosi endl care insereaz caracterul \n i golete tamponul de ieire i
ends care insereaz caracterul \0 (terminator de ir de caractere).

// Specificarea formatului de afiare cu utilizarea manipulatorilor


#include <iostream.h>
int main() {
cout << "un numar in zecimal: " << dec << 15 << endl;
cout << "in octal: " << oct << 15 << endl;
cout << "in hex: " << hex << 15 << endl;
cout << "un numar in virgula mobila: " << 3.14159 << endl;
cout << "caracter neafisabil (escape): " << char(27) << endl;

// Convertirea unui numar n zecimal, octal i hexazecimal


#include <iostream.h>
int main()
{
int numar;
cout << "Introdu un numar zecimal: ";
cin >> numar;
// citirea unui numr zecimal
cout << "valoarea in octal = 0" << oct << numar <<endl; // afiarea numrului in octal
cout << "valoarea in hex = 0x" << hex << numar<<endl; // afiarea numrului n hexazecimal
cout << "Introdu un numar hexazecimal: ";
cin >>hex>> numar;
// citirea unui numr hexazecimal
cout << "valoarea in octal = 0" << oct << numar<<endl; // afiarea numrului in octal
cout << "valoarea in zecimal ="<< dec<< numar<<endl; // afiarea numrului n zecimal
cout << "Introdu un numar octal: ";
cin >>oct>> numar; // citirea unui numr octal
cout << "valoarea in zecimal="<< dec << numar<<endl; // afiarea numrului n zecimal
cout << "valoarea in hex = 0x" << hex << numar<<endl; // afiarea numrului n hexazecimal

22

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