CÂMPURI DE BITI
Un membru de tip întreg al unei structuri poate fi declarat ca fiind reprezentat în memorie pe un numãr specificat de biti, cuprins între 1 si numãrul maxim de biti pe care este memoratã o variabilã de acel tip. Un astfel de membru se numeste câmp de biti.
Exemplul 1. În cazul unui joc de cãrti, o carte de joc poate fi reprezentatã printr-o structurã:
struct Carte {
unsigned char valoare;
//un numãr cuprins între 1 si 14
unsigned char culoare;
//un numãr cuprins între 0 si 3
};
Pentru culoare se pot utiliza constantele simbolice
#define CARO 0
#define CUPA 1
#define PICA 2
#define TREFLA 3
Pachetul de cãrti fiind
reprezentat de vectorul:
Dacã sizeof(unsigned char) este 1, atunci sizeof ( pachet ) va da ca rezultat 104. Însã este evident cã nu aven nevoie de 8 biti , cât are unsigned char, pentru a reprezenta valoarea sau culoarea unei cãrti. Pentru valoare sunt suficienti 4 biti, iar pentru culoare 2. De aceea se va da o nouã definitie a structurii Carte, utilizând câmpuri de biti:
struct carte {
unsigned valoare : 4; //
4 biti -> [0,15]
unsigned culoare : 2; //
2 biti -> [0, 3]
};
struct carte Pachet[52];
Obsevatie. Câmpurile de biti
trebuie sã aibã tipul int sau unsigned.
Dacã s-ar fi declarat
<camp_de_biti> ::= <tip_int> [<ident>]
<expresie_const_int>
<tip_int> ::= int | unsigned
Cu câmpurile de biti se pot efectua aceleasi operatii si sunt
referite în acelasi mod ca si oricare
membru al structurilor. Sã considerãm urmãtorul program.
#define CARO 0
#define CUPA 1
#define PICA 2
#define TREFLA 3
void main()
{
struct carte Pachet[52];
int nr_oct=sizeof(Pachet);
Pachet[1].valoare=7;
Pachet[1].culoare=CUPA;
printf("\nLung. pachet=%d
octeti. Cartea este (%d,%d)",
nr_oct, Pachet[1].valoare, Pachet[1].culoare );
}
Iesirea produsã de program:
Lung. pachet=52 octeti. Cartea este (7,1) |
Reprezentarea fizicã a câmpurilor
de biti (aliniere, posibilitatea ca
un câmp sã se întindã pe mai multe unitãti
de alocare) este dependentã de masinã.
Bitii neutilizati ai unei variabile structurate nu pot fi folositi
de altã variabilã structuratã. Într-un câmp
de biti reprezentat pe int, bitul cel
mai semnificativ este este considerat, de regulã, bit de semn.
Exemplul 2. Rezultatul produs de programul de mai jos
depinde de "masinã".
#include <stdio.h>
void main()
{
struct ExUnBit {
int bits_1 :1, bits_3 :3;
unsigned bitu_1:1, bitu_3:3;
} o;
o.bits_1 = o.bitu_1 = 1; //se
memoreaza bitii '1' si '1'
o.bits_3 = o.bitu_3 = 7; //se
memoreaza bitii '111' si '111'
printf ("%d %d %d %d", o.bits_1, o.bitu_1, o.bits_3, o.bitu_3);
}
Rezultat:
-1 1 -1 7 |
Exemplul 3.
struct student {
char nume[20];
unsigned an_nastere:11
; // [0,2048]
unsigned sex:1 ;
unsigned :2; // se lasa
liberi 2 biti
unsigned notaex1:4, calific1:1;
unsigned :0; // urmatorul
membru va incepe
// la o noua unitate de alocare a memoriei
unsigned notaex2:4; //4
este nr. de biti
} x;
Se va observa cã variabila structuratã
x este reprezentatã pe 24 octeti,
dar dacã se va elimina câmpul de biti unsigned
:0; atunci x va ocupa doar 23 de octeti. În loc de unsigned
:0; se putea utiliza unsigned :6; cu
acelasi efect.
Utilitatea câmpurilor de biti constã
în economia de memorie
UNIUNI
O uniune reprezintã tot un tip structurat,
însã, spre deosebire de structuri, membrii unei uniuni utilizeazã
în comun aceeasi zonã
de memorie.
Exemplul 4.
// Programul union.c
// PSG/30/03/2000
#include <stdio.h>
#define Print printf("\nx.i=%d
x.r=%e", x.i, x.r)
void main()
{
union numar
{
int i;
float r;
};
typedef union
numar NUMAR;
NUMAR x;
x.i=1980;
Print;
x.r=1980.0;
Print;
}
x.i=1980 x.r=8.431804e-16
x.i=-32768 x.r=1.980000e+03 |
Important. La un moment dat numai o singurã valoare este retinutã în variabila union.
Uniunile sunt utilizate tot pentru a face economie de memorie în cazul unor variabile care pot avea multiple interpretãri. Rãmâne în sarcina programatorului sã asigure o gestiune corectã a membrilor unei uniuni.
Exemplul 5.
// Programul union2.c Un exemplu
de struct cu union
// PSG/30/03/2000
#include <stdio.h>
#define CHAR 0
#define INT 1
#define FLOAT 2
#define DOUBLE 3
#define POINTER 4
#define
Print(x) printf(format[a.tip], x);
typedef
union {
char c;
int i;
float r;
double d;
void *p;
} valoare;
typedef
struct {
char tip; // indica tipul membrului val, care
valoare val; // este o uniune
} VARIABILA;
void Afisare
(VARIABILA);
void main()
{
VARIABILA x;
printf("\nO valoare intreaga: ");
x.tip=INT; x.val.i=1980;
Afisare (x);
printf("\nUn pointer: ");
x.tip=POINTER; x.val.p=&x;
Afisare (x);
}
void Afisare
(VARIABILA a)
{
static char *format[]={ "%c", "%d", "%f", "%lf", "%p"};
switch (a.tip) {
case CHAR: Print (a.val.c);
break;
case INT: Print (a.val.i);
break;
case FLOAT: Print (a.val.r);
break;
case DOUBLE: Print (a.val.d);
break;
case POINTER: Print (a.val.p);
break;
default: printf("Err.Tip incorect");
break; //preventiv
}
}
Rezultat:
O valoare intreaga: 1980
Un pointer: 392C:0FF6 |
Se va observa faptul cã sizeof(x)
este egal cu sizeof(char)+sizeof(val),
iar sizeof(val) este egal cu sizeof(double),
deoarece toti membrii unei uniuni partajeazã
aceeasi zonã de memorie, având
dimensiunea egalã cu dimensiunea maximã
a membrilor sãi.
typedef struct {
char octetl, octeth;
} OCTETI;
union Cuvant {
char c;
OCTET bit;
CUVANT oct;
OCTETI zona;
unsigned u;
} cuv={0};
void PrintBiti ( OCTET );
void main()
{
cuv.c = 'A';
cuv.oct.high.b0=1;
printf("\nCar=%c cuv=%x
bitul" "6=%d\n", cuv.zona.octetl, cuv.u,
cuv.bit.b6);
PrintBiti (cuv.oct.high);
PrintBiti (cuv.oct.low);
}
void PrintBiti ( OCTET o)
{
printf("%d%d%d%d." , o.b7,
o.b6, o.b5, o.b4);
printf("%d%d%d%d ", o.b3,
o.b2, o.b1, o.b0);
}
[Pagina universitatii] [Pagina facultatii] [Catalog biblioteca] [Pagina prof. St.Gh.Pentiuc]