Limbajul c si C++ abc-doar


(directa sau indirecta) a datelor arhivate.Exersati cat mai multe exemple



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

(directa sau indirecta) a datelor arhivate.Exersati cat mai multe exemple

de declarare si apelare a datelor,atat prin metode directe,cat si prin

metode indirecte(prin pointeri).
POINTERI:-sunt variabile care contin o adresa de memorie(locatia unui

obiect declarat anterior).Cel mai frecvent este adresa unei alte variabile

motiv pentru care se spune ca o variabila o indica pe cealalta(de unde si

denumirea de pointer-in engleza point=a arata,a tinti).Se declara la fel

ca orice variabila dar se va adauga si caracterul *(asterix) in fata iden-

tificatorului,pentru a specifica faptul ca este o variabila pointer.


-51-

Sintaxa generala este de tipul:

SPECIFICATOR DE TIP * Identificator

EXEMPLU: char *Pointer1

Pointeri nu sunt date structurate dar se pot utiliza pentru a forma

structuri,uniuni,enumerari sau tablouri de pointeri.In plus,fata de

variabilele simple contin si abilitatea de a accesa memoria,fapt ce

permite prezentarea lor impreuna cu structurile de date.

Specificatorul de tip se utilizeaza pentru a desemna tipul de baza al

pointerului,adica tipul de date asupra carora va actiona.

Pentru atribuirea adresei de memorie se utilizeaza operatorul &.

EXEMPLU: int *m; //declara pointerul

m=&x; //m primeste adresa variabilei x

q=*m //q primeste valoarea lui x

Pentru atribuirea valorii arhivate la adresa respectiva se va utiliza

operatorul *(asterix) care este complementar lui &.

Aceste notatii se preteaza la numeroase confuzii,deoarece caracterul

* poate fi utilizat si pentru operatiile de multiplicare iar & este si

operator AND binar.Semnificatia lor este generata de contextul in care

apar,iar in situatiile in care apar in aceeasi expresie operatorii de

pointer au precedenta fata de cei aritmetici.Este preferabil totusi ca

declararea pointerilor si operatiile cu pointeri sa se faca prin expre-

sii distincte(sau sa se adauge comentarii explicative la program).

Orice variabila(inclusiv pointerii) se caracterizeaza printr-o va-

loare(nula sau nenula) si o adresa de memorie unde este arhivata valoa-

rea respectiva.Pointerii permit accesarea ambelor tipuri de informatie

despre o variabila oarecare.Locatia de memorie este denumita uneori si

l-valoare iar valoarea obiectului respectiv este denumita uneori si

r-valoare,dupa pozitia din ecuatia adresa=valoare.Toate datele de tip

r-valoare sunt si l-valoare(toate valorile au o adresa in memorie) dar

nu toate datele l-valoare sunt si r-valoare(nu toate adresele de memorie

contin valori).In diverse manuale,apar aceste denumiri(si altele).

Expresiile care contin pointeri se formuleaza la fel ca celelalte.

Unui pointer i se poate atribui si valoarea unui alt pointer.

EXEMPLU: int x;

int *p1,*p2;

p1= &x;

p2=p1; //p2 primeste valoarea lui p1

Operatiile permise cu poinerii sunt adunarea si scaderea.Prin increment-

are cu unu,pointerul va contine adresa elementului urmator din tablou,

iar prin scadere va contine adresa elementului precedent.

Trebuie remercat faptul ca la nivel de memorie operatiile sunt deter-

minate de tipul datelor.Astfel,in cazul datelor de tip double long la

care fiecare element este reprezentat pe 10 octeti,incrementarea unui

pointer cu un element determina un salt in memorie de 10 octeti(pana la

elementul urmator).

Doi pointeri pot fi comparati prin expresii relationale.Comparatia se

va referi in acest caz la adresa de memorie continuta.Astfel o expresie

de genul p

p este inferioara celei din q(anterioara in cazul memoriei stiva).

Un tablou poate fi reprezentat numai din pointeri.

EXEMPLU: int *x[10] //un tablou de 10 pointeri de tip int


-52-

Un pointer poate contine adresa unui alt pointer,care contine adresa

unui alt poiner etc.Aceasta situatie poarta numele de adresare indirecta.

Pentru a declara un pointer catre un alt pointer se va adauga inca un

asterix.EXEMPLU: float **bilant; //este un pointer spre un alt pointer

Daca este nevoie de mai multi pointeri (rar) se pot utiliza paranteze,

pentru a declara explicit acest lucru. EXEMPLU float *(*(*bilant));

Este posibil sa declarati un pointer,iar in cursul programului,acesta

sa-si schimbe adresa de memorie accidental.Pentru a depista nivelul de

program la care a intervenit eroarea,se poate fixa un "nivel de intreru-

pere" pe pointerul respectiv.In acest fel,la derularea programului,se va

face pauza in punctul in care pointerul primeste o valoare.In cazul in

care pointerul este orientat corect dar in aria de memorie este o valoare

incorecta,se poate fixa un "nivel de intrerupere"(breakpoint) pe valoarea

pointerului respectiv,caz in care programul se va intrerupe in momentul

in care aria pointata isi schimba valoarea.In acest sens,selectati din

meniul Edit optiunea Breakpoints,alegeti Data iar in caseta de dialog

introduceti identificatorul(p) sau valoarea (*p) pointerului respectiv.

Un pointer catre date de tip void poate fi convertit in orice alt tip

de pointer,dar numai prin o declaratie explicita a tipului.Un pointer

catre orice tip poate fi convertit implicit in pointer catre void.

In situatii speciale,se poate crea un pointer spre obiecte care exista

doar in timpul executiei programului,fara a avea o adresa fixa de memorie.

Acest gen de pointeri se numesc "Pointer moniker" se se realizeaza utili-

zand functia CreatePointerMoniker.

EXEMPLU: WINOLEAPI CreatePointerMoniker(

LPUNKNOWN punk,

LPMONIKER FAR *ppmk

);

Pentru operatii intre membrii unei clase si pointeri se pot utiliza

operatorii .* si ->* (vezi operatorii).Operatiile cu pointeri au sens

doar atunci cand acestia pointeaza arii formate din mai multe elemente.

Pointerii spre un element unic,nu participa la operatii aritmetice sau

relationale.

Pointerii pot fi convertiti dintr-un tip de date in altul,cu conditia

ca tipul de date final sa ocupe tot atata spatiu de memorie,sau mai putin.

Pointerii pot fi declarati si in mod automat,dinamic,utilizand functia

DYNAMIC_DOWNCAST care declara si verifica pointerul de clasa declarat.

Pointerii sunt un instrument de lucru extrem de util al limbajului C si

C++,dar trebuie manevrati cu foarte multa atentie,deoarece pot modifica

datele din adresele de memorie (accidental sau intentionat) de asa maniera

incat sa defecteze sistemul de operare(sunt instrumentul preferat al cre-

atorilor de "virusi informatici").Orice program care contine pointeri ce

produc programe defective prin alterarea memoriei va fi considerat si

tratat juridic ca si un "virus informatic" premeditat,autorul nu va putea

utiliza scuza unei "greseli accidentale" sau a necunoasterii implicatiilor

rezultate.

Pointerii pot fi utilizati si in medii de programare complexe care

contin rutine scrise in limbaje diferite.Astfel,de exemplu,in limbajul

Fortran,pentru a extrage adresa unei variabile se utilizeaza functia LOC.

Pentru a transfera o astfel de adresa,dintr-o rutina scrisa in Fortran in

aplicatia de baza scrisa in limbaj C sau C++ se va utiliza un pointer.


-53-

STRUCTURI
Reprezinta un set de mai multe elemente de acelasi tip de data,sau de

tipuri diferite.In alte limbaje de programare poarta numele de "records"

(inregistrari) sau "procedure"(proceduri) etc.Se utilizeaza pentru a

putea grupa functii si date,pentru a putea fi accesate in bloc.Definitia

unei structuri poate fi utilizata si ca sablon pentru formarea unor alte

structuri similare.In general,functiile si datele grupate intr-o struc-

tura au o legatura logica intre ele.Identificatorul,denumit si "tag",este

facultativ dar este foarte util pentru a face referinta la structura de-

clarata.Declararea se face utilizand cuvantul cheie "struct"

Sintaxa generala este: struct [identificator]

{

[]

...

}[]

Numele precizat prin identificator(tag-ul),poate fi utilizat pentru refe-

rirea la o structura definita in alta zona a programului.Daca o structura

a fost deja definita,iar definitia este "vizibila"(adica este incarcata

in memoria de lucru a programului),atunci lista de declaratii din struc-

tura nu poate fi redeclarata.Tag-ul se poate utiliza si pentru declararea

pointerilor spre structura respectiva.Mai mult,in cazul pointerilor se

poate utiliza tag-ul(numele) viitor al unei structuri ce nu a fost inca

declarata.Structura nu poate fi utilizata insa decat dupa declarare.

Fiecare variabila declarata in lista de declaratii va reprezenta un

membru al structurii.Membrii unei structuri pot fi de orice tip,cu ex-

ceptia tipului void si a tipului incomplet.

Numele unei structuri(identificatorul),trebuie sa fie unic in cadrul

aceleasi zone de vizibilitate(zona de lucru a programului).

Fiecare declaratie din lista de declaratii trebuie sa fie unica.In

interiorul structurii,se pot utiliza si denumiri(identificatori) care

apar si in interiorul unei alte structuri(deoarece nu sunt in aceeasi

zona de vizibilitate a programului) dar nu pot fi repetate denumirile

pentru variabilele declarate externe(globale).

Declaratiile vor contine si tipul de date,pentru fiecare membru.

EXEMPLU: struct Adresa

{

char nume[30];

char strada[40];

char oras[20];

char stat[10];

unsigned long int cod_postal;

};

Declaratia unei structuri se termina cu punct si virgula,deoarece este

considerata ca si o instructiune si trebuie returnat controlul la nivelul

de baza(functia main()).

Optional,structura poate fi si initializata in momentul declararii prin

.

Structurile pot fi intricate("imbricate"),una in cealalta ,caz in care

structura din interiorul celeilalte se va comporta ca si un membru al

structurii respective.


-54-

Daca o structura a fost declarata fara o lista de variabile(nu a fost

initializata),atunci declaratia doar descrie structura dar nu poate fi

utilizata(nu are memorie alocata).

Dupa declarare,referirea la un membru al structurii se face utilizand

operatorul punct.

EXEMPLU: struct numar{

float real;

float imaginar;

}a

Pentru a accesa cei doi membri ai numarului complex se vor utiliza for-

mulele a.real si a.imaginar.

Un membru al unei structuri poate fi accesat si indirect,printr-un

pointer,utilizand operatorul ->*

EXEMPLU: struct numar{

float real;

float imaginar;

}a,ptr*=&a;

Pentru a desemna pointerul spre fiecare membru al structurii se va

utiliza prt->*real sau ptr->* imaginar

O structura poate si sa se autorefere,adica sa contina un pointer care se

orienteaza spre propria structura.

EXEMPLU: struct pair

{

int a;

int b;

struct pair *sp;

} item,list[10];

Prin item.sp=&item pointerul va aloca adresa de memorie a propriei struc-

turi.in mod similar se poate atribui unui pointer adresa de memorie a

oricarui membru din structura.Observati ca in cazul membrilor formati din

tipuri de data diferite,si adresele de memorie alocate pentru fiecare

membru vor fi diferite ca lungime in octeti.

Informatia continuta intr-o structura poate fi atribuita unei alte

structuri,cu conditia sa fie definita la fel.

EXEMPLU: struct numere {

int a;

int b;

} x,y;

x.a=10; //membrul a este initializat 10

y=x; //structura x se atribuie lui y

In urma operatiei,elementul y.a va fi gata initializat la valoarea 10.

Sutucturile pot fi grupate in tablouri,pentru a forma diverse instru-

mente de calcul tabelar de genul conoscutului program "Excel" sau "Lotus".

In acest caz,fiecare element al tabloului va fi format din cate o struc-

tura care contine la randul sau un numar de elemente.Rezulta un complex

bidimensional de date structurate,foarte util pentru calcul tabelar.

EXEMPLU: struct calcul{

char ch;

int i;

float c;

} tab[2][3] // tablou bidimensional


-55-

Tabloul de structuri va putea fi initializat prin:

{ //initializarea tabloului

{ //initializarea liniei

{'nume1',1,1.2} //initializarea primei structuri

{'nume2',2,3.4}

{'nume3',3,5.6}

}

{ //initializarea liniei urmatoare

{'nume4',4,7.8} //initializare prima structura din linia 2

{'nume5',5,9.9}

}

};

Datele arhivate vor fi de forma:

[0][0] nume1 1 1.2

[0][1] nume2 2 3.4

[0][2] nume3 3 5.6

[1][0] nume4 4 7.8

[1][1] nume5 5 9.9

[1][2] 0 0
Elementele unei structuri pot fi transmise unei functii,adica se va

transfera valoarea unui membru al structurii,valoare ce va fi apoi uti-

lizata in cadrul functiei pentru efectuarea operatiilor.

EXEMPLE: struct date

{

char x;

int y;

float z;

char s[10];

} adrese;

Pentru a transfera valoarea unui membru catre o functie se vor utiliza:

func(adrese.x); //transmite valoarea lui x (de tip caracter)

func(adrese.y) //transmite valoarea lui y (de tip int)

func(adrese.s[2] //transmite valoarea membrului 3 din tabloul s

Este posibila transferarea intregii structuri ca argument al unei functii,

caz in care atat argumentul cat si parametrul functiei trebuie sa fie de

acelasi tip.In versiunile vechi de C,acest transfer integral nu este

posibil structurile fiind tratate la fel ca si tablourile.

EXEMPLU: struc date1 {

int a,b;

char ch;

};

void f1(struct date1); //se transfera structura

Intr-o structura este importanta ordinea in care se declara fiecare

membru,deoarece se vor arhiva in memorie in ordinea declararii.Primul

membru declarat va avea adresa de memorie cea mai mica iar ultimul decla

rat va avea adresa de memorie cea mai mare.Eventual se poate utiliza

pachetul #pragma pack,pentru a controla modul de arhivare in memorie a

datelor in forme cat mai compacte(valoarea implicita este cea de 8 bytes).

O structura din limbajul C este echivalenta cu RECORD din FORTRAN sau

cu class din limbajul C++(class contine si atribute suplimentare).


-56-

UNIUNI
Sunt structuri in care toti membrii utilizeaza aceeasi adresa de me-

morie si se substitue reciproc(se suprascriu reciproc).Adresa de memorie

are dimensiunea adaptata pentru tipul de date al membrului care ocupa cel

mai mult spatiu.O uniune poate contine variabile de tipuri diferite,un

identificator denumit tag(eticheta) si este la fal ca si structura,echi-

valenta cu RECORD din limbajul Fortran,sau PROCEDURE din FoxPro.

Declararea se face la fel ca si pentru structuri(respecta aceleasi reguli

fundamentale).Fata de structuri,ocupa mai putin spatiu de memorie,permit

tratarea mai multor tipuri de date in aceeasi arie de memorie,permit

diverse conversii ale tipurilor de date,contin o singura variabila la

un anumit moment dat.Uniunile pot include si campuri de biti.Membrii unei

uniuni nu pot fi de tip void sau incomplet.

EXEMPLU: union sign

{

int svar;

unsigned uvar;

} numar;

Declara o uniune de tip sing,formata din doi membri si salvata in varia-

bila numar.

Daca se salveaza o variabila de un anumit tip,iar apoi uniunea este

accesata cu un alt tip de data,rezultatul poate fi imprevizibil(Exemplu:

numerele int vor putea fi reprezentate intr-o variabila float,dar nu si

viceversa).Rezervarea de memorie pentru o uniune se face doar in momentul

declararii variabilei.Tipul de data al reuniunii este ultimul tip de

data atribuit.Utilizatorul este responsabil de pastrarea evidentei pentru

tipul curent de data(daca nu exista o rutina special destinata) si respec-

tiv pentru apelarea corecta a datelor curente.

Pointerii catre uniuni se realizeaza la fel ca si cei spre structuri.

Valoarea unei uniuni poate fi atribuita unei functii.Se pot forma tablouri

din uniuni,pentru a realiza tabele multifunctionale(afiseaza succesiv,nu-

mele,adresa,telefonul,contul curent etc.).Uniunile pot fi intricate una

in alta,ca si cand ar fi membri simpli,sau pot fi incluse in structuri.

Nu pot fi utilizati ca membri ai uniunii,clasele de date automate(cu con-

structor si destructor),clasele de date care contin operatori artizanali(

cu definitie precizata de catre utilizator) sau datele declarate static(

mai multi membri trebuie sa poata utiliza adresa de memorie).

Pentru declarare se utilizeaza cuvantul cheie union.Sintaxa generala este:

typedef [atribute] union [tag] {

declaratii membrii

......

} numeuniune;

Atributele acceptate sunt:helpstring,helpcontext,uuid,hidden si version.

EXEMPLU: union nume1

{

char ch;

int i;

long l;

float f;

} parola; // poate fi utilizata pentru arhivarea parolei


-57-

In limbaj C++,o uniune este considerata ca si o clasa de date,dar cu

unele limitari.Poate avea specificatori de acces de tipul public,private

sau protected,membri formati din date sau din functii (inclusiv construc-

tori si destructori),dar nu poate contine functii virtuale sau membri

declarati statici.Nu poate avea clasa de baza si nici nu poate fi clasa

de baza pentru alte clase.Accesul implicit este cel de tip public.

Operatiile asupra uniunii sunt la fel ca pentru structuri.

EXEMPLU: union cod1

{

int i;

double d;

} var1;

var1.i=6 //va arhiva valoarea 6 (tip int)

var1.d=5.327 //va suprascrie valoarea 5.327(double)
CAMPURI DE BITI (bit fields)
Se utilizeaza in cadrul declaratiilor de membri ai unei structuri sau

uniuni,pentru a preciza explicit,bit cu bit,modul in care vor fi arhivate

datele in memorie.Dimensiunea campului de date in care trebuie incadrata

declaratia depinde de formatul suportului de memorie(Exemplu: in cazul

versiunii MS-DOS pe 16 biti,dimensiunea maxima a campului de biti va fi

de 15,iar in cazul versiunii Windows pe 32 de biti va fi de 31 de biti).

Sintaxa generala este:

struct-numele(tag-ul){

declarator

specificator de tip declarator:constanta

unde constanta specifica largimea in biti a campului de biti.Specifica-

torul de tip trebuie sa fie unsigned int,signed int sau int,iar constanta

trebuie sa fie o marime intreaga pozitiva.Nu se pot declara tablouri de

tip camp de date,dar se pot forma tablouri din structuri ce contin campuri

de date.

EXEMPLU: struct imagine

{

unsigned short icon : 8;

unsigned short color : 4;

unsigned short underline : 1;

unsigned short blink : 1;

Yüklə 4,6 Mb.

Dostları ilə paylaş:
1   ...   4   5   6   7   8   9   10   11   ...   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