variabile referint˘ a c++ ˘si clase de echivalent˘ avancea/flp/suport_curs/slides...apare ^ n...
TRANSCRIPT
Variabile Referinta C++ si Clase de EchivalentaFundamentele Limbajelor de Programare
VANCEA Alexandru
Departamentul de InformaticaUniversitatea Babes-Bolyai
Cluj-Napoca, 2018
TipDeData& nume variabila
Acestea nu sunt variabile pointer. Sunt variabile care exprimalucrul la nivel de adresa si se folosesc ıntr-unul dintre urmatoarele 3moduri:
I pentru a defini alieriint i;int& j = i; // j - nume alternativ pentru iint k = 9;j = k; // de fapt i = 9 !
I pentru a transmite parametrii unui subprogram prinreferintavoid f(double & a) { ... a += 9.27; ... }...double d = 12.75;f(d);
I pentru a returnare L-valori (lvalues)int v[20];...int& g(int i) { ... return v[i]; ... }...g(3) = 7; // v[3] = 7;
int& F1(int* talou, int& intreg) {...int& altintreg = tablou[intreg]; // aliere !intreg = altintreg / 3; // apel prin ref !...return tablou[altintreg]; // returnare lvalue
}...int i = 1;int a[] = 14, 6, 15, 3, 21, 31, 16;...F1(a, i) = 40; // a[6] = 40 !
int const& j = i; // are semnificatia ca j NU poate fi lvaluej = 17; // nu este permisSe foloseste pentru alieri ın regim de readonly. Este util ıntransmiterea prin referinta a unei structuri mari
int& j = 25; // pana la C++ 2.0 - se creeaza o variabila anonima(dummy variabile) aliata cu locatia constantei.Din C++ 2.1 - syntax error!Reference initialized with in needs lvalue of type int!
Declaratie Expresie de tip Tipul
int i int ıntreg
int* pi int* pointer la ıntreg
int *p[3] int *[3] tablou de 3 pointeri la ıntreg
int (*p)[3] int (*[3]) pointer la untablou de 3 ıntregi
int *f() int *() functie fara argumentece ıntoarce pointer la ıntreg
int (*pf)(double) int(*)(double) pointer la functiecu argument double ce
ıntoarce pointer la ıntreg
// transforma numele de variabila ıntr-un nume de tip de date.typedef declaratie de variabila;
char* (**f[10]) (int);// f este pointer la un tablou de 10 pointeri la functii// ce au argument int si returneaza un pointer la chartypedef char* f2(int);typedef f2* A[10];A* f;
D.p.d.v. sintactic exista 3 acceptiuni ale echivalentei tipurilor.
I echivalenta structurala (C)
I echivalenta de nume (C++ ımpreuna cu toate limbajele custructura de bloc)
I echivalenta de declarare
Doua tipuri sunt echivalente structual daca si numai dacacomponentele lor sunt aceleasi din toate punctele de vedere
struct A int x, y;struct B int x, y;Sunt compatibile ın C, si NU sunt compatibile ın C++
Echivalentadeclarativa ⇒ Echivalentanume ⇒ Echivalentastructurala
Echivalenta de declarare are loc numai daca variabilele ale carortipuri sunt considerate echivalente, apar sub aceeasi declarare detip
type T = array[5..20] of real;var x, y : array[5..20] of real;var z : array[5..20] of real;var w : T;var a : array[1..10, 1..10] of integer;var b : array[1..100] of integer;var w1: T;
Ed En Es
x y DA DA DA
x z NU [1] DA
a b NU NU NU
w w1 NU DA DA
z w [2]
[1] Echivalenta de nume ın cazul tipurilor de date anonime seimplementeaza ın doua moduri:
I se compara string-urile reprezentand tipurile de date, iar dacaare loc identitatea, atunci echivalenta de nume are loc
I compilatorul atribuie diferite valori fiecarui tip de data anonim/ fiecarei declaratii de tip
[2] de obicei sunt considerate compatibile
extern f(struct A*)struct A { int x, y; };struct B { int x, y; };void g(struct A* pa, struct B* pb){
f(pa); // ok in C si C++f(pb); // ok in C (Es), syntax error C++ (En)pa = pb; // ok in C (Es), syntax error C++ (En)pa = (struct A*) pb; // ok in C si C++
}
In ce situatii apare necesitatea verificarii compatibilitatii de tip?Care sunt situatiile ın care compilatoarele verifica existenta acestorcompatibilitati?
I compatibilitate la atribuire
I compatibilitate la transmiterea de parametrii
I compatibilitate la calculul de expresii
Raspunsul este dat de definitia limbajului si eventual de anumiteconditionari date de implementarea compilatorului
Accidental booleansif ( a = b ) { ... };if ( 0 ¡ a ¡ 5 ) { ... };
Nivel de Inglobare Statica
Apare ın Algol, Pascal, Modula, Ada, Delphi, dar in C NU.Limbajele cu structura de bloc accepta ıntotdeauna nivele deınglobare statica mai mari decat 1 (adica definirea de subrutinelocale ın interiorul unor functii/proceduri), ın schimb standardullimbajului C nu accepta, aici toate functiile definite fiind la nivelul1 (adica nu putem defini functii ın interiorul altor functii).Implementarea compilatorului gcc accepta implementarea de nivelede ınglobare de nivele mai mari decat 1, asta fiind o exceptie acompilatorului.
Problema Dangling Reference
Utilizarea pointerilor ın limbajele de programare pot provoca douaerori de tip logic.Plecand de la o legatura pointer - entitate, putem identificaurmatoarele doua situatii:
I ıncetarea duratei de viata a pointerului (dealocareapointerului)Presupunand ca entitatea pointata este alocata ın heap si esteo variabila dinamica, suntem ın situatia ın care acea entitatereprezinta o valoare reziduala si inaccesibila, avand necesitateaexistentei / activarii unui instrument de tip garbage collector.
I ıncercarea de a accesa o entitate ınainte de initializare apointerului ce o refera sau ıncercarea de a accesa o locatiedupa ce aceasta a fost eliberata sunt situatii de tip danglingreference
program unu;var x: ˆinteger; { pointer la integer }procedure P;
var y: ˆinteger;begin
y := 7;x := @y; { adresa lui y }
end;begin;
P;writeln(xˆ); { dereferentiere }
end;
program doi;var x: ˆinteger; { pointer la integer }procedure P;
var y: ˆinteger;begin
new(y);yˆ := 7;x := y; { syntax error: ”type mismatch” (Pascal
implementeaza En; ˆinteger este tip anonim (ˆinteger esteexpresie de tip, nu este nume de tip) }
end;begin;
P;writeln(xˆ);
end;
program doi;type pint = ˆinteger;var x: pint;procedure P;
var y: pint;begin
new(y);yˆ := 7;x := y;
end;begin;
P;writeln(xˆ);
end;
program trei;var x: ˆinteger; { pointer la integer }procedure P;
var y: ˆinteger;begin
new(y);yˆ := 7;x := @yˆ;dispose(y);
end;begin;
P;writeln(xˆ);
end;
Utilizarea Constantelor de Tip String ın C si C++
char v[25];int f(char* s);int f(char s[]);int f(char s[25]);f(v);
sizeof(’a’) =
I 1 ın C++
I 2 ın BorlandC
I 4 ın GCC
sizeof(”a”) = 2; // [’a’, ’\0’]”abcd”[2] = ’c’Valoarea asociata unei constante asociate unui sir de caractere esteadresa sa de ınceput
a)char* s;...gets(s);...// eroare logica// (nu s-a alocat// spatiu pentru// string-ul punctat// de s)
b)char* s;...s = ”abcd”;...s = malloc(...);...// OK
c)char s[10];...gets(s);// eroare logica// pentru string-uri// mai lungi// decat 10...s = malloc(...);// syntax error
d)char s[10];...s = ”abcd”;// syntax error
e)char s[] = ”abcd”;// syntactic sugar
In cazurile a) si b),s este variabilade tip pointer
In cazurile c) si d),s este o constantade tip pointer
1)char* f(...){ ... char s[15]; ... return s; }// solutie: static char s[15];
2)char* f(...){ char* s; gets(s); ... return s; }// solutie: s = malloc(...);