ARRAY COME PUNTATORI


Nel linguaggio C gli array sono realizzati come una successione di variabili distinte allocate una dopo l'altra e l'array è essenzialmente un puntatore, precisamente un puntatore alla variabile che corrisponde al primo elemento dell'array.
Pertanto in C esiste una dualità tra array e puntatori di cui è bene essere consci.

Consideriamo questa dualità su un esempio
ARRAYPUNTATORE
int x[10]; int *px;
questa dichiarazione corrisponde a dichiarare 10 variabili di tipo int allocate in celle consecutive, con x inteso come un modo per riferirsi a x[0]. px è una variabile che contiene un indirizzo di variabile intere.
Seguendo la metafora variabile=scatola in questo caso abbiamo
valgono che
x == &x[0]
&x[1] == (&x[0])+1
&x[2] == (&x[1])+1
...
&x[9] == (&x[8])+1
dopo aver eseguito px = &x[0]; si ha che valgono
*(px+1) == x[1]
...
*(px+9) == x[9]
x non è una variabile, quindi x = ...; è erratopx è una variabile, quindi px = ...; è corretto


ESEMPIO
#include <stdio.h>

main(){
    int x[10] = {0,1,2,3,4,5,6,7,8,9};
    int * px = NULL, z;
    
    px = &x[0];
    px = px+1;
    
    if(x[1] == *px) printf("va bene \n");
    else printf("va male\n");
    
    if(x == &x[0]) printf("torna tutto \n");
    else printf("qualcosa non va\n");
    
    px = px +2;
    printf("il valore del contenuto di px e\' %d\n",*px);
    
    px = &x[0];
    /*x = x+1; errore*/
    z = px[3];
    printf("il valore di px[3] e\' %d\n",z);
    /*z = (*px)[3]; errore*/
    z = *(px+3);
    printf("il valore di *(px+3) e\' %d\n",z);

}
produrrà come output
va bene 
torna tutto 
il valore del contenuto di px e' 3
il valore di px[3] e' 3
il valore di *(px+3) e' 3

Una conseguenza di questa peculiarità del C riguarda i parametri delle funzioni di tipo array: come al solito sono parametri valori, ma i parametri di tipo array sono dei puntatori al primo elemento, quindi effettivamente essi sono dei parametri variabili.

Pertanto se volete un parametro valore di tipo array dovete controllare voi di non modificarlo all'interno della funzione; se invece volete un parametro variabile di tipo array, non dovete fare nulla (diversamente dal caso di un parametro variabile di altri tipi, vedere qui).
Si consiglia di indicare con dei commenti quando un parametro adi tipo array è un valore e quando è una variabile.


ESEMPIO
#include <stdio.h>
#define DIM 5

int VSum(int v[] /*valore*/, int dim)
{
   int sum = 0, i;
   
   for(i=0; i < dim; i++)
      sum += v[i];
   return sum;
}

int VSumP(int * pv, int dim)
{
   int sum = 0, i;
   
   for(i=0; i < dim; i++)
      sum += *(pv+i);
   return sum;
}

void VPrint(int v[ ] /*valore*/, int dim)
{
   int i;
   
   for(i=0; i < dim; i++)
      printf("%5d ",v[i]);
    printf("\n");
}

void VPrintP(int * pv, int dim)
{
   int i;
   
   for(i=0; i < dim; i++){
      printf("%5d ",*pv);
      pv = pv+1;
   };
   printf("\n");
}

void VRead(int v[ ] /*variabile*/, int dim)
{
   int i;
   
   for(i=0; i < dim; i++)
      scanf("%d",&v[i]);
}

void VReadP(int * pv, int dim)
{
   int i;
   
   for(i=0; i < dim; i++)
      scanf("%d",pv+i);
}

main(){
    int a[DIM] = {3,3,3,3,3}, b[DIM];
    
    VPrint(a,DIM);
    VPrintP(a,DIM);

    VRead(b,DIM);
    VPrint(b,DIM);
    
    VReadP(b,DIM);
    VPrint(b,DIM);

    printf("La somma e\' %d.\n",VSum(a,DIM));
    printf("La somma P e\' %d.\n",VSumP(&a[0],DIM));
    printf("La somma di un postfisso (ultimi 2 elementi) e\'   %d.\n",VSum(a+2,2));
    printf("La somma di un postfisso P (ultimi 2 elementi) e\'   %d.\n",VSumP(a+2,2));

}

ESERCIZIO
  1. Modificare i programmi visti precedentemente utilizzando, quando possibile, la dualità del C tra array e puntatori per rimpiazzare un array con il suo corrispondente puntatore.