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:

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.

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]
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:

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.

#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]
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).

#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;
        }
      }
    }
}

6. Initializare