Documente Academic
Documente Profesional
Documente Cultură
Daniela Saru - "Programarea calculatoarelor. Note de curs” – Ed. Printech, 2011 / slides rev. 2021 120
Ex.
struct data struct data
{ int zi; ambele forme {int zi, luna, an;};
int luna; descriu tipul de date
int an; numit struct data
};
struct data astazi; declararea variabilei numite astazi, de tipul struct data
Ex.
struct clx
{ float re; definire tip structură + declarare a 2 variabile (z1 şi z2)
float im;
} z1, z2;
Ex.
struct numele structurii poate lipsi dacă definirea se face
{ float re; odată cu declararea variabilelor (Acest stil nu se
float im; recomandă!)
} z1, z2;
Daniela Saru - "Programarea calculatoarelor. Note de curs” – Ed. Printech, 2011 / slides rev. 2021 121
Ex.
struct clx { float re; float im;}; /* definire tip */
Ex.
/*o altă variantă de definire a unui nume nou pentru un tip structură*/
typedef struct { float re; float im;} NR_CLX;
NR_CLX z1, z2;
Daniela Saru - "Programarea calculatoarelor. Note de curs” – Ed. Printech, 2011 / slides rev. 2021 121
Obs.
- Forma generală de utilizare a cuvântului cheie typedef este:
typedef Definire_Tip NumeNou;
- Câteva exemple de utilizare a acestei facilităţi pentru alte tipuri de date decât tipul
structură:
typedef unsigned char BYTE;
BYTE m,n; /* 2 variabile de tip unsigned char */
Daniela Saru - "Programarea calculatoarelor. Note de curs” – Ed. Printech, 2011 / slides rev. 2021 122
Tipul structură: reuneşte sub un singur nume componente de tip simplu şi/sau
structurat ce pot fi folosite individual sau ca grup (global).
Ex.
struct data astăzi, mâine, data_scrisoare;
astăzi.zi = 23;
astăzi.luna = 11; lucru pe componente;
astăzi.an = 2021;
mâine.zi = astăzi.zi + 1;
data_scrisoare = astazi;
Spaţiul de memorie alocat celor trei variabile din exemplul anterior va arăta astfel:
zi zi zi
23 24 23
astăzi luna mâine luna data_scrisoare luna
11 11
an 2021 an an 2021
Daniela Saru - "Programarea calculatoarelor. Note de curs” – Ed. Printech, 2011 / slides rev. 2021 122
8.2 Operaţii cu structuri
Daniela Saru - "Programarea calculatoarelor. Note de curs” – Ed. Printech, 2011 / slides rev. 2021 123
OBS: două structuri nu se pot compara global. Pentru a realiza această operaţie
este necesară scrierea instrucţiunilor care compară explicit componentele
corespondente ale celor două structuri:
Exemple didactice….
Daniela Saru - "Programarea calculatoarelor. Note de curs” – Ed. Printech, 2011 / slides rev. 2021 123
Ex: NR_CLX rezultat (float x, float y) /*NR_CLX definit anterior cu typedef*/
{ NR_CLX z;
z.re = x;
z.im = y;
return z;
}
float real(NR_CLX z)
{ return z.re;}
float imaginar(NR_CLX z)
{return z.im;}
Daniela Saru - "Programarea calculatoarelor. Note de curs” – Ed. Printech, 2011 / slides rev. 2021 124
OBS. Atunci când se lucrează cu funcţii, se preferă de multe ori transmiterea ca parametru a
unui pointer la structură. Notaţiile utilizate pentru utilizarea componentelor structurii, în acest caz,
sunt similare celor prezentate în exemplul următor.
Apelare: NR_CLX z;
………….
conjugare(&z); /*valoarea lui z va fi modificată */
Daniela Saru - "Programarea calculatoarelor. Note de curs” – Ed. Printech, 2011 / slides rev. 2021 124
/*Pe baza datei calendaristice curente, programul următor calculează şi afişează pe
ecran data zilei de mâine, folosind câte 2 cifre pentru zi, lună şi an.*/
struct data
{ int zi;
int luna;
int an;
}; /*definirea tipului structură ce va fi folosit în întreg programul*/
int nr_de_zile (struct data d); /*calculează numărul de zile din lună/*
int este_an_bisect (struct data d); /*verifică dacă anul este sau nu bisect*/
Daniela Saru - "Programarea calculatoarelor. Note de curs” – Ed. Printech, 2011 / slides rev. 2021 125
void main(void)
{ struct data azi, maine;
Daniela Saru - "Programarea calculatoarelor. Note de curs” – Ed. Printech, 2011 / slides rev. 2021 125
/*funcţia care calculează numărul de zile din lună*/
int nr_de_zile (struct data d)
{ int zile_în_lună [12] = {31,28,31,30,31,30,31,31,30,31,30,31};
if (este_an_bisect(d) && d.luna == 2)
return 29; /*nr. de zile din luna februarie a unui an bisect*/
else
return zile_în_lună [d.luna – 1];
}
Daniela Saru - "Programarea calculatoarelor. Note de curs” – Ed. Printech, 2011 / slides rev. 2021 126
8.3 Iniţializarea structurilor
DAR...
De exemplu:
struct data azi = {30, 11}; /*echivalent cu: azi.zi = 30; azi.luna = 11;
azi.an ramane neiniţializat – valoare nedefinită*/
Daniela Saru - "Programarea calculatoarelor. Note de curs” – Ed. Printech, 2011 / slides rev. 2021 126
8.4 Tablouri de structuri şi structuri care conţin tablouri
Exemplu (declarare):
void afiseaza (struct data x); /*prototip de funcţie*/
...
struct data aniversare [15]; / *tablou cu 15 elemente de tip struct data */
...
aniversare [1].zi = 30;
aniversare [1].luna = 4;
aniversare [1].an = 2003; /*s-au dat valori elementului aniversare[1]*/
afiseaza(aniversare [1]); /*se foloseşte elementul de tip structură al
tabloului ca parametru al funcţiei*/
Exemplu (iniţializare):
struct data aniversare [3] = {{30,4,2003},{15,6,2000},{3,2,2007}};
=>
.zi 30
aniversare[0] .luna 4
.an
2003
.zi 15
aniversare[1] .luna
6
.an
2000
.zi
aniversare[2] .luna 3
.an 2
2007
Daniela Saru - "Programarea calculatoarelor. Note de curs” – Ed. Printech, 2011 / slides rev. 2021 127
8.5 Structuri ierarhizate
Un tip structură care conţine componente de tip structură se mai numeşte şi
„structură ierarhizată”.
Exemplu: moment de tip caracterizat prin oră, minut, secundă, dar şi data
calendaristică asociată (zi, lună, an):
data_si_timp
data timp
Daniela Saru - "Programarea calculatoarelor. Note de curs” – Ed. Printech, 2011 / slides rev. 2021 127
struct data { int zi, luna, an; }; /*definire de tip structură*/
struct timp { int ora, minute, secunde; }; /*definire de tip structură*/
struct data_si_timp
{ struct data primul;
struct timp al_doilea;
} eveniment; /*definire de variabilă*/
struct data_si_timp examen={ {2, 2, 2010} , {9, 0, 0} }; /*declarare cu iniţializare*/
/*eveniment.primul => un membru al structurii numite eveniment*/
eveniment.primul.luna=10; /*membru al structurii primul*/
++eveniment.al_doilea.secunde; /*membru al structurii al_doilea*/
Daniela Saru - "Programarea calculatoarelor. Note de curs” – Ed. Printech, 2011 / slides rev. 2021 128
8.7 Forme particulare de structuri
Uniunea
Structura cu variante
Câmpul de biţi
Daniela Saru - "Programarea calculatoarelor. Note de curs” – Ed. Printech, 2011 / slides rev. 2021 138
8.7.1 Uniunea
Daniela Saru - "Programarea calculatoarelor. Note de curs” – Ed. Printech, 2011 / slides rev. 2021 138
union Nume
{ long i; Variabila exemplu nu va putea conţine, simultan, 2 valori
float f; distincte (pentru câmpurile i şi f), ci va conţine o singură
} exemplu; valoare (fie pentru câmpul i, fie pentru câmpul f)
Spaţiul necesar alocării unei variabile de tip union este determinat pe baza
informaţiilor specificate la declarare. În exemplul anterior, daca long int si float sunt
reprezentate pe câte 4 octeţi, reprezentarea internă a uniunii arată astfel:
i sau f
Daniela Saru - "Programarea calculatoarelor. Note de curs” – Ed. Printech, 2011 / slides rev. 2021 139
Dimensiunea uniunii este suficient de mare pentru a putea cuprinde cel mai mare
câmp, dar nu este neapărat egală cu dimensiunea acestuia, ci poate fi mai mare
sau egală.
Cei interesaţi pot găsi detalii suplimentare despre acest subiect în bibliografia sau
Webografia de specialitate.
Tipul struct poate sa apară în tipul union şi reciproc. Oricare combinaţie poate să
apară în tipul tablou.
Daniela Saru - "Programarea calculatoarelor. Note de curs” – Ed. Printech, 2011 / slides rev. 2021 139
union AltNume ocupă spaţiu >= cu dimensiunea celui
{ struct mai „voluminos” câmp component
{ char c1, c2; } s; 2000 2001 2002 2003
long i;
float f;
} ceva; s, i sau f
union Geaman
{ char c[2];
long i;
float f;
} altceva;
obţinem aceeaşi reprezentare internă ca şi pentru variabila numită ceva, dar putem
atribui valori astfel:
altceva.c[0] = ‘a’;
altceva.c[1] = ‘b’;
Daniela Saru - "Programarea calculatoarelor. Note de curs” – Ed. Printech, 2011 / slides rev. 2021 140
Declarare: în cazul uniunilor se folosesc aceleaşi reguli sintactice ca pentru structuri.
Iniţializare:
în cazul uniunilor numai primul membru se poate iniţializa cu o expresie
constantă (între acolade).
O variabilă automatică uniune se poate iniţializa cu o altă variabilă automatică
de acelaşi tip.
Pentru a accesa componentele unei uniuni se foloseşte operatorul punct (.)
sau săgeată (->), dacă se utilizează pointeri.
Daniela Saru - "Programarea calculatoarelor. Note de curs” – Ed. Printech, 2011 / slides rev. 2021 140
Exemplu preluat din volumul „Iniţiere în limbajul de programare C” - Dorin Irimescu,
Litografia UPB, 1992
Transmisia se poate face însă numai serial (octet după octet), astfel încât informaţiile
trebuie recompactate după recepţionare.
În acest scop, se poate defini un tip union care să permită interpretarea grupului de
octeţi recepţionaţi (de exemplu, 8 octeţi) ca o unică valoare de tip real – dublă precizie.
Daniela Saru - "Programarea calculatoarelor. Note de curs” – Ed. Printech, 2011 / slides rev. 2021 141
/*interpretarea diferita a datelor intr-o uniune*/
char citeste_octet (void); /*prototipul unei functii pe care nu o vom detalia aici*/
union val_dubla_prec
{ char c[8];
double val;
}; /*definirea tipului union*/
Daniela Saru - "Programarea calculatoarelor. Note de curs” – Ed. Printech, 2011 / slides rev. 2021 141
8.7.2 Structura cu variante
Presupunem că dorim să scriem un program care să ţină evidenţa persoanelor ce
urmează să se prezinte la interviu în vederea angajării la o firmă. Firma oferă posturi
extrem de diverse, atât pentru persoane calificate cât şi pentru persoane necalificate.
Din acest motiv, un minimum de informaţii despre candidaţi ar putea fi structurat
astfel:
- nume şi prenume;
- data naşterii;
- sex;
- studii:
- şcoală generală – caz în care nu se mai cer alte informaţii;
- liceu sau şcoală profesională – se cere media de absolvire;
- facultate – se cer informaţii despre:
- numele facultăţii;
- media de absolvire;
- master;
- cursuri postuniversitare.
Este evident că dacă am crea un tip structură cu caracter general care să cuprindă
câte un câmp pentru fiecare dintre informaţiile menţionate s-ar irosi mult spaţiu de
memorie deoarece, de exemplu, în cazul unui candidat care a absolvit doar şcoala
generală rămân nefolosite toate câmpurile asociate liceului şi facultăţii.
Daniela Saru - "Programarea calculatoarelor. Note de curs” – Ed. Printech, 2011 / slides rev. 2021 142
O rezolvare convenabilă a acestei probleme este:
definirea câmpului „studii” ca fiind de tip union
adăugarea unui câmp suplimentar numit, de exemplu, „tip_studii” care să
ia valorile întregi 1, 2 sau 3, pentru a preciza că în câmpul „studii” vom stoca
informaţii despre „şcoală generală”, „liceu sau şcoală profesională” sau
„facultate”.
Observaţie importantă:
Daniela Saru - "Programarea calculatoarelor. Note de curs” – Ed. Printech, 2011 / slides rev. 2021 142
Exemplu tipic de utilizare a unei uniuni:
/* în câmpul discriminator, de tip caracter, numit tip, vom pune valoarea:
‘C’ – dacă în câmpul uniune dorim să memorăm o valoare de tip char;
‘I’ – dacă în câmpul uniune dorim să memorăm o valoare de tip int;
‘F’ – dacă în câmpul uniune dorim să memorăm o valoare de tip float.
Funcţia ce afişează conţinutul câmpului uniune va interpreta ca “eroare” orice altă
valoare caracter găsită în câmpul discriminator*/
#include <stdio.h>
#define CARACTER ‘C’
#define INTREG ‘I’
#define REAL ‘F’
struct exemplu
{ char tip; /*câmpul discriminator, de tip caracter, numit tip*/
union informatie
{ char c;
int i;
float f;
}valoare; /*câmpul de tip uniune, numit valoare*/
}; /*s-a încheiat definirea tipului structură*/
Daniela Saru - "Programarea calculatoarelor. Note de curs” – Ed. Printech, 2011 / slides rev. 2021 143
void afisare(struct exemplu d)
{ printf("\n Valoarea este...");
switch ( d.tip )
{ case CARACTER: printf("%c", d.valoare.c); break;
case INTREG: printf("%d", d.valoare.i); break;
case REAL: printf("%f", d.valoare.f); break;
default: printf("tip necunoscut: %c\n",d.tip);
}
}
void main(void)
{ struct exemplu a;
a.tip = CARACTER; /*vrem ca semnificatia câmpului uniune sa fie “caracter”*/
a.valoare.c = ‘B’; /*stocăm informaţia în câmpul uniune*/
afisare(a);
a.tip = REAL; /*vrem ca semnificatia câmpului uniune să fie “val. reală”*/
a.valoare.f = (float) 12.34; /*stocăm informaţia în câmpul uniune*/
afisare(a);
a.tip = ‘x’; /*dăm o valoare greşită câmpului uniune*/
a.valoare.i = 111; /*încercăm să stocăm o informaţie în câmpul uniune*/
afisare( a ); /*va genera mesajul de “eroare”…*/
}
Pe ecran:
Valoarea este...B
Valoarea este...12.34
Valoarea este...tip necunoscut: x
Daniela Saru - "Programarea calculatoarelor. Note de curs” – Ed. Printech, 2011 / slides rev. 2021 143
8.7.3 Câmpul de biţi
În limbajul C, cel mai „mic” tip este tipul char, reprezentat intern pe 1 octet (8 biţi).
În variabile de tip struct sunt necesare uneori şi de câmpuri cu lungime mai mică de 1
octet (câmpuri ale căror valori sunt întotdeauna mai mici decât 255!).
Singura restricţie impusă în acest caz este că valorile câmpului pot fi numai de tip
int sau char.
Daniela Saru - "Programarea calculatoarelor. Note de curs” – Ed. Printech, 2011 / slides rev. 2021 144
Ex: struct ex
{ unsigned a:1;
unsigned b:3;
unsigned :4;
unsigned c:3;
unsigned d:2;
} exemplu;
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
d c biţi nefolosiţi b a
câmpul fără nume
După cum se poate observa, câmpurile de biţi permit folosirea judicioasă a spaţiului de
memorie în funcţie de domeniul de valori pe care îl acoperă:
Câmp Valori
exemplu.a 0.....1
exemplu.b 0.....7
exemplu.c 0.....7
exemplu.d 0.....3
Daniela Saru - "Programarea calculatoarelor. Note de curs” – Ed. Printech, 2011 / slides rev. 2021 144
Câmpurile de biţi sunt “împachetate” în unităţi de memorare care au dimensiune
egală cu a tipului int (2 octeţi, în cazul nostru). Dacă numărul de octeţi pe care se
reprezintă tipul int este de 4, unitatea de memorare va ocupa 4 octeţi!
Lungimea fiecărui câmp de biţi va fi, în general, mai mică sau cel mult egală cu cea a
unităţii de memorare.
Câmpurile fără nume pot fi folosite pentru alinierea (plasarea) următorului câmp de
biţi la începutul octetului următor.
Dacă un câmp fără nume are lungime 0 (zero), următorul câmp de biţi se aliniază la
adresa de început a următoarei unităţi de memorare.
Daniela Saru - "Programarea calculatoarelor. Note de curs” – Ed. Printech, 2011 / slides rev. 2021 145
Utilitate:
- Permit folosirea eficientă a spaţiului de memorie;
- Permit folosirea unor structuri de date de formă impusă;
- Permit încadrarea într-o formă de reprezentare internă impusă;
- Simplifică lucrul la nivel de bit, dar codul generat este voluminos;
Daniela Saru - "Programarea calculatoarelor. Note de curs” – Ed. Printech, 2011 / slides rev. 2021 145
Exemplu de utilizare (didactic)
Structura definită în exemplul anterior (struct ex) poate permite afişarea anumitor
grupuri de biţi din reprezentarea internă a unui întreg (16 biţi):
union test
{ struct ex cifre; Cp_biti.C
unsigned short w;
} u;
unsigned short x;
printf(“Tastaţi valoarea lui x:”);
scanf(“%hu”,&x);
u.w = x;
printf(“Valorile câmpurilor din reprezentarea internă a lui x, conforme tipului
struct ex, sunt:\n”);
printf(“d=%u c=%u b=%u a=%u\n”, u.cifre.d, u.cifre.c, u.cifre.b, u.cifre.a);
Daniela Saru - "Programarea calculatoarelor. Note de curs” – Ed. Printech, 2011 / slides rev. 2021 146
Un exemplu practic de utilizare a câmpurilor de biţi dar şi a operatorilor la
nivel de bit este descris în articolul intitulat „How to Program an 8-bit
Microcontroller Using C language” – Richard Mann, Imagecraft
http://ww1.microchip.com/downloads/en/DeviceDoc/avr_3_04.pdf
Daniela Saru - "Programarea calculatoarelor. Note de curs” – Ed. Printech, 2011 / slides rev. 2021 146