Limbajul c si C++ abc-doar


Regulile de sintaxa par complicate la prima vedere,dar sunt in esenta



Yüklə 4,6 Mb.
səhifə10/55
tarix07.05.2018
ölçüsü4,6 Mb.
#50260
1   ...   6   7   8   9   10   11   12   13   ...   55

Regulile de sintaxa par complicate la prima vedere,dar sunt in esenta

lor destul de simple si intuitive.Cu putina practica,devin chiar usoare.

Sunt indispensabile atunci cand definiti clase de obiecte.Pentru inceput,

este bine sa utilizati clase de obiecte cat mai simple si clare,cu nu

mai mult de doua sau trei clase derivate si/sau intricate,in cate puteti

sa observati din ochi calea de acces la fiecare membru al claselor.Pentru

structuri mai complicate,este bine sa desenati pe hartie cu pataratele

arhitectura datelor structurate declarate si sa urmariti caile de acces

la fiecare dintre membri,astfel incat programul sa fie cat mai usor de

declarat.

Versiunile mai noi ale limbajului C++(de exemplu Visual C++ 6.0) au

simplificat foarte mult aceasta problema,prin adaugarea unui numar foarte

mare de clase de obiecte predefinite,inclusa intr-o biblioteca de obiecte

de 1 Gb care contine clase de obiecte predefinite pentru aproape toate

tipurile posibile de aplicatii.In plus,clasele MFC sunt si ordonate ierar-

hic,astfel incat si regulile si clauzele de acces sunt gata rezolvate si

nu mai necesita nici un efort din partea programatorului.Biblioteca MFC,

contine circa 250 de astfel de clase de obiecte predefinite,structurate

dupa tipul de aplicatie(arhitectura,grafica,ferestre,comenzi,meniuri etc.)

Cu ajutorul acestei biblioteci,programatorul alege doar din arborele ie-

rarhic clasa cea mai potrivita si o introduce in aplicatia sa.

Programul mai include de altfel inca doua biblioteci,respectiv ATL

(adica Active Template Library) si OLE DB (adica Object Linked Embadded

Data Bases) care contin clase predefinite parametrizate si exemple de

obiecte generate cu clase C++.

Pentru o intelegere cat mai intuitiva a modului de editare si respectiv

a modului de executie a unui program in limabj C++,cea mai simpla compa-

ratie este cea cu jocul de domino(principiul domino-ului) sau cu jocul de

puzzle sau scrabble.Cei pasionati ai acestor jocuri,vor aprecia mult mai

usor fatetele limbajului C++.Inconvenientul consta in faptul ca majorita-

tea aplicatiilor vor functiona dupa principiul "totul sau nimic",fapt ce

determina nenumarate complicatii in munca de depanare a programelor.


-65-

CONVERSII ALE TIPURILOR DE DATE
Obiectele din clase diferite pot fi convertite la alt tip de date.In

acest sens sa va construi un obiect din tipul final de date,folosind ca

sursa obiectul initial.Procesul se numeste conversie prin constructor,

deoarece utilizeaza constructorul obiectului initial si apoi schimba

doar specificatorul de tip.

Conversiile intre date din tipurile fundamentale(int,char,float etc.)

se numesc conversii standard.Conversiile standard sunt:-promotia integrala

conversia integrala,conversia in virgula mobila,conversia integrala si in

virgula mobila,conversia aritmetica,conversia pointerilor,conversia re-

ferintei,conversia din pointer in membru.

Promotia integrala-obiectele de tip int pot fi convertite in alte

obiecte de tip int dar mai mari(ocupa mai multi bytes/data).Se poate uti-

liza pentru obiecte,siruri de caractere si constante de tip char si short

int,enumarari,campuri de biti de tip int sau enumeratori.

Conversia integrala-are loc intre date de tip integral(char,int,long)

si versiunile lor(short,signed,unsigned).

In cazul conversiei din signed in unsigned,in urma conversiei se pastreaza

valoarea absoluta,dar se poate pierde semnul minus astfel incat evaluarea

expresiilor va determina rezultate diferite.Exemplu : daca short i=-3 este

convertit la unsigned short i acesta va deveni 3.

In cazul conversiei din unsigned in signed,pot apare erori atunci cand

valorile unsigned sunt mai mari decat domeniul de valori signed.(Exemplu

unsigned short y=65000 este in afara domeniului fata de signed short y).

Atunci cand datele de tip intreg sunt convertite in alte date de tip

intreg dar mai mici(ocupa un spatiu mai mic si au domeniu de valori mai

restrans),procesul poarta numele de conversie standard si poate avea ca

rezultat pierderea de date,atunci cand valoarea convertita este mai mare

decat domaniul de valori al tipului final de date.

Conversia in virgula mobila-se refera la conversia datelor de tip

float,in date de tip float cu precizie mai mare:din float in double sau

din double in long double.In acest caz conversia este sigura si se pas-

treaza valorile.In cazul conversiei datelor cu precizie mare in date cu

precizie mai mica(Exemplu din long double in float),conversia este sigura

doar daca valoarea se afla in domeniul de reprezentare al datei finale,iar

in caz contrar va rezulta o data nedefinita(data infinita).

EXEMPLU: cout <<(float)1E300<

poate reprezenta doar numere pana la 1E+38.

Conversia dintre datele integrale si cele in virgula mobila decurge

astfel: -conversia datelor float in int se face prin trunchierea partii

fractionale fara rotunjire(Exemplu 3.14 devine 3)

-conversia datelor int in float este de obicei facila.Daca valoa-

rea originala nu poate fi reprezentata exact,atunci se va utiliza valoarea

imediat apropiata(mai mica sau mai mare) dintre cele reprezentabile.

Conversia aritmetica-daca intr-o expresie apar doi operanzi de tipuri

diferite,atunci cel de tip mai mic va fi convertit la tipul mai mare de

date,astfel incat datele sa fie representabile(Exemple: din int in float,

din float in double sau long double etc.).Procesul prin care operatorii

aritmetici binari convertesc datele pentru a fi reprezentabile,se numeste

conversie aritmetica uzuala.


-66-

Pointerii pot fi convertiti in timpul operatiilor de atribuire,initiali-

zare,comparatie etc.

-o constanta care returneaza zero sau o expresie de tip void poate fi

convertita la untip de pointer denumit "pointer null" care se va com-

porta diferit de orice tip de pointer orientat spre o functie sau un

obiect valid.

-pointerii spre tipul void pot fi convertiti in oricare alt tip de

pointeri.Un pointer spre un obiect incomplet(definit dar fara valoare,

sau fara clasa de baza definita) poate fi convertit in pointer spre

tipul void si viceversa.

-un pointer spre orice obiect care nu este "const" sau "volatile" poate

fi convertit in pointer de tipul void

-un pointer spre orice functie poate fi convertit la tipul void daca

tipul void* poate include acel pointer(daca spatiul de memorie este

suficient).

-un pointer spre o clasa,poate fi convertit in pointer spre clasa de

baza in doua situatii:-1.daca clasa de baza este accesibila (este de-

clarata "public") si conversia nu este ambigua si 2.daca se precizeaza

explicit conversia dorita(operatie de atribuire explicita)

-o expresie de tip arie poate fi convertita la un pointer.Rezultatul

este un pointer spre elementul zero(primul) al ariei.

EXEMPLU: char szPath[_MAX_PATH}; //arie de tip caracter

char *pszPath=szPath // este egala cu &szPath[0]

-pointerii spre membrii unor structuri de date(struct,class) se com-

porta diferit de pointerii obisnuiti si nu respecta conventiile stan-

dard de converise de mai sus(cu exceptia pointerilor spre membrii de

tip static).Pointerii spre membrii se realizeaza cu operatorii ::*,

.* si ->* se refera al funciile si membrii structurii respective.

Nu exista conventii de conversie pentru datele declarate de tip const

sau volatile,dar in situatiile care se preteaza la astfel de conversii

acestea pot fi specificate explicit.

Conversia pentru referinte:-o referinta la o anumita clasa poate fi con-

vertita la o referinta spre clasa de baza,cu conditia ca clasa de baza

sa fie accesibila(declarata "public") iar converisa sa nu fie ambigua

(sa fie precizate explicit denumiri distincte si unice).

Conversia pointerilor catre membrii claselor se poate face in urmatoarele

situatii:

-conversia unui membru care este o constanta cu valoarea zero se poate

face spre un "pointer null".

-conversia unui pointer spre un membru al clasei de baza catre un

pointer spre un membru al unei clase derivate din clasa de baza se

poate face daca este posibila si conversia inversa(de la clasa derivata

spre clasa de baza) adica ambele clase sunt accesibile si daca clasa

derivata nu a mostenit de la clasa de baza un membru virtual (daca nu

este incomplet definita).
In afara conversiilor standard,descrise mai sus,tipurile de date pot fi

convertite si prin definitii explicite precizate de catre utilizator.

Pentru a fi valide,conversiile explicite precizate de catre utilizator

trebuie sa nu fie ambigue(sa utilizeze nume distincte si unice pentru aria

de vizibilitate respectiva.


-67-

FUNCTII
Prototipul unei functii trebuie sa stabileasca numele functiei,tipul

de date returnat de catre functie,respectiv numarul si tipul parametrilor

sai formali.

Declararea unei functii se poate face in interiorul unei alte funcii,

caz in care se numeste functie definita intern,sau locala,sau cu vizibi-

litate locala.Daca declararea unei functii se face in afara oricarei alte

structuri de date,atunci functia este globala,sau cu vizibilitate globala

sau "cu vizibilitate in toata fila program".Indiferent daca au fost decla-

rate intern sau extern,definitia functiei trebuie facuta intotdeauna ex-

tern(spre deosebire de variabile care pot fi definite si intern).

Singurii specificatori care modifica declaratia unei functii sunt

"static" si "extern" prin care se determina daca functia poate sau nu

poate fi referita din alte file ale programului."Extern" este implict.

Tipul de date returnat de functie se precizeaza prin specificatorii de

tip(void,char,int,float etc.) si poate fi oricare dintre tipurile funda-

mentale.Tipul atribui implicit este int.Rezultatul evaluarii functiei va

fi returnat in momentul in care executia ajunge la o instructiune RETURN.

Argumentele functiei sunt nume de valori se se trensmit functiei in

momentul apelarii.Parametrii sunt valori pe care functia se sconteaza ca

la va lua in timpul executiei.In prototipul unei functii,lista completa a

parametrilor este inclusa intre parantezele ce urmeaza dupa numele fun-

ctiei.In declaratie,parametrii trebuie sa specifica tipul,marimea si va-

loarea parametrilor.

Parametrii functiilor declarati cu "auto" genereaza erori.Fiecare para-

metru trebuie sa fie precedat de specificatorul sau de tip.

EXEMPLU: void new(double x,double y,double z)

{

x=y*z // expresia care defineste functia

};

Daca in lista de argumente a functiei figureaza cel putin un parametru,

atunci lista poate sa se incheie cu o virgula urmata de trei puncte(,...)

prin care se indica faptul ca functia poate avea argumente variabile.No-

tatia poarta numele de "ellipsis notation".

Corpul functiei este un bloc compact de expresii prin care se specifica

ce anume face functia respectiva si se include intre acolade.Variabilele

declarate in corpul functiei vor fi "locale",adica vor fi vizibile doar

in interiorul functiei.

In timpul executiei unui program,controlul trece peste definitia unei

functii pana cand intalneste instructiunea RETURN,moment in care evalueaza

functia si returneaza valoarea(este important atunci cand depanati un pro-

gram).

Argumentele functiei se trec intre parantezele ce urmeaza numelui,sub

forma de lista.Daca functia nu are nici un argument se va utiliza speci-

ficatorul void.

Argumentele pot fi din oricare dintre tipurile fundamentale de date,

pot fi structuri sau uniuni de date sau pointeri.Toate argumentele se

transfera functiei prin valoarea lor.

Argumentele nu pot fi arii sau functii,dar pot fi pointeri orientati

spre aceste tipuri de date.


-68-

Apelarea(solicitarea) unei functii se face prin o expresie ce include

numele functiei respective.O expresie care apeleaza o functie,va returna

o valoare de aceeasi tip cu cel al functiei apelate.Functiile nu pot

returna obiecte de tip arie(nu lucreaza cu arii).Daca o functie este de

tip void si rezultatul apelarii functiei va fi tot de tip void.

La evaluarea unei functii,daca este necesar,se fac automat si con-

versiile standard intre argumentele functiei,astfel incat rezultatul

evaluarii sa fie reprezentabil.

O functie poate fi apelata si recursiv,adica sa se apaleze pe sine.In

acest caz functia contine in corpul sau si o expresie prin care se auto

apeleaza pana cand se indeplineste o anumita conditie.Numarul de bucle de

repetitie este determinat de volumul de memorie alocat in stiva pentru

parametrii functie.La fiecare reapelare,se vor arhiva in stiva noile

valori ale parametrilor si ale variabilelor "auto" si "register".In unele

situatii,acest gen de functii ajung sa depaseasca volumul de memorie.

O functie poate avea un numar variabil de parametri,caz in care acestia

vor fi specificati utilizand notatia "ellipsis" (,...).In absenta acestei

notatii,functia nu poate primi parametri aditionali fata de cei declarati

in lista de parametrii.Se utilizeaza pentru functii care vor primi si

parametri suplimentari fata de cei declarati initial.Pentru apelarea unei

astfel de functii,se va specifica numele functiei si un numar oarecare de

argumente.

EXEMPLU: int medie(int primul,int secundul,...);

aceasta functie va putea face media dintre doi sau mai multi parametri

adaugati ulterior.

Pentru a obtine informatii despre legaturile din program se pot utiliza

functiile specializate Call Graph(prezinta toate functiile pe care le

apeleaza functia respectiva) sau Callers Graph(prezinta toate functiile

din care este apelata functia respectiva).

Supraincarcarea functiilor(function overloading) este procedeul prin

care se declara mai multe functii cu acelasi nume,in acelasi domeniu de

vizibilitate.Prin acest procedeu se pot declara functii cu semantica

diferita cu numar diferit de argumante sau cu tipuri de date diferite.

Compilatorul C++,nu numai ca permite acest procedeu dar si selecteaza

dintre definitiile functiei pe cea care este cea mai potrivita cu tipul

de date utilizat in program (operatie de altfel hazardata si nerecomanda-

bila in majoritatea situatiilor-rezultatul poate fi nescontat).

Versiunile profesionale ofera si instrumente cu care se poate efectua

un profil al functiilor din program(timpul de executie,functiile accesate,

functiile neaccesate sau atributiile functiilor accesate).

Prototipul functiilor stabileste numele functiei si tipul returnat,cat

si numarul parametrilor formali(nu include si corpul functiei).

Functiile template,sunt functii parametrizate.Se utilizeaza pentru a

defini familii de functii cu parametri standardizati.

Functiile pot fi grupate in fisiere separate,caz in care toate fun-

ctiile vor fi incarcate in memorie in bloc,sau pot fi arhivate sub forma

de bibiloteci,caz in care se vor putea incarca in memorie doar acele

functii de care este nevoie pentru executia programului.

Limabjul C contine o biblioteca standard cu peste 500 de functii,gata

implementate pentru o mare diversitate de aplicatii,functii ce trebuiesc

incarcate selectiv,inainte de incarcarea aplicatiei in care actioneaza.


-69-

PREPROCESORUL C
Toate elementele prezentate anterior sunt incluse in executabilul

care contine rutinele programului C si sunt incarcate in memoria de lucru

la fiecare pornire a programului.Elementele descrise sunt suficiente

pentru efectuarea de operatii complexe sau de analiza si sinteza a datelor

dar nu contin elemente pentru comunicarea cu utilizatorul si nici facili-

tati de afisare si prezentare grafica a datelor sau a rezultatelor.

Pentru comunicarea cu utilizatorul(afisare pe ecran,imprimare,grafica,

introducerea de date de la tastatura,mouse etc.) sunt necesare functii

auxiliare ce se vor incarca selectiv,in functie de necesitatile fiecarei

aplicatii.Aceste functii sunt arhivate in biblioteca standard a progra-

mului.Pentru a putea fi utilizate in program,trebuie sa existe in memorie.

Din acest motiv,functiile auxiliare se incarca la pornirea aplicatiei cu

ajutorul unor directive denumite "de preprocesor",deoarece sunt executate

in etapa premergatoare celei de procesare a datelor.

Astfel,programarea unei aplicatii incepe cu alegerea functiilor auxili-

are necesare si incarcarea lor in memorie cu ajutorul comenzii #include.

Preprocesorul este de fapt un procesor de text care manipuleaza fragmente

de text din fila sursa(declaratii de functii) in etapa initiala a fazei

de transcriere(compilare) a datelor din program.Preprocesorul nu face

analiza sintactica a expresiilor ci doar le separa in unitati distincte

(token) si le incarca in memorie.Pentru a obtine o lista a codului sursa

dupa preprocesare se poate utiliza optiunea de compilare /E sau /EP.

Prin preprocesare,se vor incarca in memorie,atat fila de coduri sursa

redactata de utilizator cat si filele cu date auxiliare specificate prin

comenzi #include,realizand astfel programul complet,denumit si unitate de

translatare.Din filele adaugate,se pot exclude conditional,una sau mai

multe expresii utilizand comenzi de genul #if.

Diferitele file ce contin coduri sursa pot comunica intre ele prin:

-apeluri catre functii specificate de tip "extern"

-apeluri catre membri ai functiilor declarati de tip "extern"

-modificare directa a obiectelor declarate de tip "extern"

-modificare directa a filelor sursa(inserari,deletii etc.)

-comunicatii intre procesari (numai pentru Microsoft Windows)

Etapele succesive ale procesului de compilare a programelor sunt:

1.-Character mapping-caracterele sunt reprezentate intern

2.-Line splicing-liniile de cod sunt defragmentate

3.-Tokenization-codul sursa este fragmentat in elemente (token)

4.-Preprocessing-se executa comenzile de preprocesare

5.-Character-set mapping-secventele de caractere sunt convertite in

echivalentul lor executabil

6.-String concatenation-se executa concatenarea sirurilor

7.-Translation-fiecare token(element sintactic) este analizat seman-

tic si sintactic si convertit in cod obiect

8.-Linkage-se rezolva toate solicitarile catre file externe astfel

incat sa rezulte un program executabil sau o biblioteca dinamica.

Se observa ca preprocesarea are loc inaintea analizei sintactice si a

generarii de legaturi intre elementele programului.

Daca exista erori de formulare sau incompatibilitati care blocheaza

executia comenzilor,compilatorul va genera mesaje de eroare.


-70-

Directivele de preprocesare sunt:#define,#error,#if,#elif,#else,#endif

#ifdef,#import,#include,#line,#undef si comanda nula.

#define -se utilizeaza pentru a denumi o constanta in program

In urma utilizarii,constanta respectiva(elementul din program) va fi inlo-

cuita in toate aparitiile urmatoare din program.

Sintaxa este: #define identificator(nume) token-string(element sau sir)

EXEMPLU: #define test (f1,f2)(f1*f2)

Daca numele identificatorului nu este urmat de un token,atunci identifica-

torul va fi sters din toate aparitiile sale ulterioare din program.

Exemplu: #define test va strege identificatorul "test" din program

Yüklə 4,6 Mb.

Dostları ilə paylaş:
1   ...   6   7   8   9   10   11   12   13   ...   55




Verilənlər bazası müəlliflik hüququ ilə müdafiə olunur ©muhaz.org 2024
rəhbərliyinə müraciət

gir | qeydiyyatdan keç
    Ana səhifə


yükləyin