5.5. Variabile registru
2019/02/26 in Programare in C
O variabila alocata intr-un registru al calculatorului se numeste variabila registru. Ea se declara printr-o declaratie obisnuita precedata de cuvantul cheie register.
Se pot declara, ca variabile registru, numai variabilele de tip int, char si pointer (care va fi introdus in capitolul urmator). De asemenea, numai parametrii si variabilele automatice simple pot fi declarate ca variabile registru.
Numai un numar limitat de variabile se pot aloca in registri. Alocarea ramane valabila pana la revenirea din functie. In cazul in care nu pot fi alocate in registri toate variabilele registru declarate de programator, se aloca cate se pot in ordinea declararii lor, iar restul se aloca in mod obisnuit pe stiva, ca orice variabila automatica sau parametru.
Se recomanda sa se declare ca variabile registru acele variabile ale unei functii care au o utilizare mare in functia respectiva. Alocarea unei variabile in registru conduce la economie de memorie, precum si la cresterea vitezei de calcul.
In lipsa declaratiilor registru compilatorul aloca in mod implicit anumite variabile automatice sau parametri in registri.
In legatura cu variabilele registru amintim ca lor nu li se poate aplica operatorul adresa (&).
Exercitii:
5.1. Sa se scrie o functie care citeste:
- valoarea variabilei m de tip int;
- valoarea variabilei n de tip int;
- m*n numere care reprezinta elementele unei matrice de ordinul m*n.
Functia are urmatorii parametri:
dmat | tablou care pastreaza elementele matricei citite; |
max | maximul produsului m*n admis. |
Functia returneaza produsul m*n si atribuie valorile lui m si n, variabilelor globale nrlin, respectiv nrcol.
Tabloul dmat este unidimensional, matricea pastrandu-se prin liniarizare.
Daca notam cu a[i,j] unde i = 0, 1, ...m-1 si j = 0, 1, ..., n-1 elementele matricei, atunci elementului a[i,j] se atribuie lui dmat[k], unde:
(1) k = i*n + j
Aceasta relatie poarta denumirea de relatie de liniarizare. Ea permite pastrarea pe linii a elementelor matricei citite. Astfel, prima linie a matricei este formata din elementele a[0,j] pentru j = 0, 1, ..., n-1. Conform relatiei (1), aceste elemente se pastreaza in itabloul dmat prin intermediul elementelor:
dmat[0], dmat[1], ..., dmat[n-1]
Linia a doua, adica elementele a[1,j], pentru j = 0, 1, ..., n-1, se pastreaza in tabloul dmat ca elemente ce au indicii
k = 1*n + j
, adica:
dmat[n], dmat[n+1], ..., dmat[n + n-1]
In general, linia formata din elementele a[i,j] pentru j = 0, 1, ..., n-1 se pastreaza in tabloul dmat ca:
dmat[i*n], dmat[i*n+1], ..., dmat[i*n + n-1]
Functia de fata foloseste Functia ndcit definita la exercitiul 4.37.
- FUNCTIA089A.C - Citire matrice si liniarizare
int gdcitmat(double dmat[], int max)
{
extern int nrlin, nrcol;
int i, m, n;
char t[255];
do {
do {
printf("numarul de linii = ");
if(gets(t) == NULL) {
printf("s-a tastat EOF\n");
exit(1);
}
if(sscanf(t, "%d", &m) == 1 && m > 0 && m <= max)
break;
printf("nu s-a tastat un intreg din intervalul [1, %d]\n", max);
} while(1);
do {
printf("numarul de coloane = ");
if(gets(t) == NULL) {
printf("s-a tastat EOF\n");
exit(1);
}
if(sscanf(t, "%d", &n) == 1 && n > 0 && n <= max)
break;
printf("nu s-a tastat un intreg din intervalul [1, %d]\n", max);
} while(1);
i = m*n;
if(i <= max)
break;
printf("produsul m*n = %d depaseste pe max = %d\n", i, max);
printf("se reiau citirile lui m si n\n);
} while(1);
if(ndcit(i, dmat) != i) {
printf("nu s-au tastat %d elemente\n", i);
exit(1);
}
nrlin = m;
nrcol = n;
return i;
}
5.2. Sa se scrie o functie care calculeaza produsul dintre o matrice de ordinul m*n si o matrice coloana (de ordinul n*1).
Functia are urmatorii parametri:
m | numarul liniilor matricei; |
n | numarul coloanelor matricei; |
dmat | tablou unidimensional de tip double care pastreaza elementele matricei de ordinul m*n prin liniarizare; |
dmatcol | tablou unidimensional de tip double care pastreaza elementele matricei coloana; |
dmatrez | tablou unidimensional de tip double care pastreaza elementele matricei rezultat. |
Matricea rezultat este de ordinul m*1. Elementele ei se calculeaza prin relatia:
dmatrez[i] = a[i,0]*dmatcol[0] + a[i,1]*dmatcol[1] +...+ a[i,n-1]*dmatcol[n-1]
pentru i = 0, 1, ..., m-1, unde prin a[i,j] am notat un element al matricei de ordinul m*n. Tinand seama de relatia de liniarizare, suma de mai sus se scrie astfel:
dmatrez[i] = dmat[i*n]*dmatcol[0] + dmat[i*n + 1]*dmatcol[1] +...+ a[i*n + n-1]*dmatcol[n-1]
- FUNCTIA089B.C - Produs matrice de ordinul m*n si o matrice coloana
void pmatcol(int m, int n, double dmat[], double dmatcol[], double dmatrez[])
{
int i, j, k;
for (i = 0; i < m; i++) {
dmatrez[i] = 0;
k = i*n;
for (j = 0; j < n-1; j++)
dmatrez[i] += dmat[k+j] * dmatcol[j];
}
}
5.3. Sa se scrie un program care citeste elementele unei matrice a de ordinul m*n, calculeaza si afiseaza produsul a*b.
In acest scop se vor apela trei functii:
- functia gdcitmat care citeste elementele matricei a (vezi exercitiul 5.1.);
- functia dvcit care citeste elementele matricei b (vezi exercitiul 4.38.);
- functia pmatcol care calculeaza produsul a*b (vezi exercitiul 5.2.);
Deoarece functiile gdcitmat si dvcit apeleaza functia ndcit se va include si fisierul care contine definitia acestei functii (vezi exercitiul 4.37.)
Matricea a va fi precedata de doi intregi care reprezinta valorile lui m si n.
Matricea b va fi precedata de un intreg care reprezinta valorea lui n. Aceasta valoare, desi pare ca nu este necesara inaintea elementelor matricei b, ea se tasteaza pe de o parte pentru a face o verificare cu privire la numarul datelor tastate, iar pe de alta parte, prezenta ei este ceruta de functia dvcit.
- Programul 089 - Produs matrice de ordin mxn si matrice coloana
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include "FUNCTIA086A.C" /* functia ndcit */
#include "FUNCTIA086B.C" /* functia dvcit */
#include "FUNCTIA089A.C" /* functia gdcitmat */
#include "FUNCTIA089B.C" /* functia pmatcol */
int nrlin, nrcol;
/* variabile globale utilizate la citirea matricei cu ajutorul functiei gdcitmat */
#define MAX 1000
main()
/* citeste elementele matricei a de ordinul m*n si /
elementele matricei b de ordinul n*1 /
calculeaza si afiseaza produsul c = a*b */
{
int m;
double a[MAX], b[MAX], c[MAX];
gdcitmat(a, MAX);
/* citeste matricea a; /
la revenire, nrlin are ca valoare numarul liniilor (m) /
iar nrcol numarul coloanelor (n) */
/* citeste matricea b*/
if (dvcit(MAX, b) != nrcol) {
printf("matricea coloana nu are %d linii\n", nrcol);
exit(1);
}
/* calculeaza produsul c = a*b */
pmatcol(nrlin, nrcol, a, b, c);
/* listeaza matricea rezultat */
for(m = 0; m < nrlin; m++) {
printf("c[%d] = %g\n", m, c[m]);
if((m+1)%23 == 0) {
printf("actionati o tasta pentru a continua\n");
getch();
}
}
}
5.4. Sa se scrie o functie care calculeaza produsul a doua matrice de tip double.
Fie a o matrice de ordinul m*n si b o matrice de ordinul n*s. Matricea:
c = a*b
este de ordinul m*s. Elementele ei se calculeaza cu relatia:
c[i,j] = a[i,0]*b[0,j] + a[i,1]*b[1,j] +...+ a[i,n-1]*b[n-1,j]
pentru i = 0, 1, ..., m-1 si j = 0, 1, ..., s-1.
Elementele celor trei matrice se pastreaza liniarizat in tablourile unidimensionale dmata, dmatb si dmatc. Folosind relatia de liniarizare, suma de mai sus se reprezinta astfel:
dmatc[i*s+j] = dmata[i*n]*dmatb[j] + dmata[i*n+1]*dmatb[s+j] +...+
+ dmata[i*n+k]*dmatb[k*s+j] +...+
+ dmata[i*n+n-1]*dmatb[(n-1)*s+j]
- FUNCTIA090.C - Produs a doua matrice de tip double
void dprodmat(int m, int n, int s, double dmata[], double dmatb[], double dmatc[])
{
int i, j, k;
int in, is;
for(i = 0; i < m; i++) {
is = i*s;
in = i*n;
for (j = 0; j < s; j++) {
dmatc[is+j] = 0;
for(k = 0; k < n; k++);
dmatc[is+j] += dmata[in+k]*dmatb[k*s+j];
}
}
}
5.5. Sa se scrie un program care citeste elementele a doua matrice de tip double, calculeaza si afiseaza produsul lor.
Programul utilizeaza functia gdcitmat pentru a citi elementele celor doua matrice. De aceea, elementele matricelor vor fi precedate de ordinul lor (numarul de linii si numarul coloanelor - vezi exercitiul 5.1. de mai sus).
- Programul 090 - Produs a doua matrice de tip double
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include "FUNCTIA086A.C" /* functia ndcit */
#include "FUNCTIA089A.C" /* functia gdcitmat */
#include "FUNCTIA090.C" /* functia dprodmat */
#define MAX 1000
int nrlin, nrcol;
/* variabile globale utilizate la citirea matricei cu ajutorul functiei gdcitmat */
main()
{
int m, n, s;
double a[MAX], b[MAX], c[MAX];
int i, j, is, k;
/* citeste matricea a */
gdcitmat(a, MAX);
m = nrlin;
n = nrcol;
/* citeste matricea b */
gdcitmat(b, MAX);
if (nrlin != n) {
printf("matricea a are %d coloane\n", n);
printf("matricea b are %d linii\n", nrlin);
exit(1);
}
s = nrcol; /* numarul coloanelor matricei b */
/* calculeaza produsul c = a*b */
dprodmat(m, n, s, a, b, c);
/* afiseaza matricea produs */
k = 0;
for(i = 0; i < m; i++) {
printf("\n\tlinia nr.%d\n", i+1);
is = i*s;
k++;
for(j = 0; i < s; j++) {
printf("%g ", c[is+j]);
if( j%5 == 4) {
/* afiseaza 5 elemente pe un rand */
printf("\n");
k++; /* numara randurile */
}
if(k == 23) {
printf("actionati o tasta pentru a continua\n");
getch();
k = 1;
}
}
}
}