ESERCITAZIONI: linguaggio C


pagine di Roberto Ricci L.S. "A. Righi", Bologna. Ultima revisione


 
 
 

Per iniziare


 
  1. Creare sul floppy A: con [Tasto Destro]Nuovo/Cartella una cartella dal nome lab9
  2. Salvare il corrente file in A: con il nome A:Es9
  3. Usare Riduci a icona per mettere da parte la finestra sul floppy senza chiuderla
  4. Aprire il file A:Es9.htm per leggere e seguire il resto dell'esercitazione
  5. Ridurre le dimensioni della finestra su A: che deve restare visibile ma consentire la visibilitÓ di un'altra nuova finestra

 
 

Variabili puntatore


  Un puntatore Ŕ una variabile il cui contenuto Ŕ un numero intero che rappresenta l'indirizzo di un'altra variabie del tipo dichiarato. In gergo si dice che la prima variabile punta alla seconda. La forma della dichiarazione di una variabile puntatore Ŕ:
<tipo dela variabile puntata> *<nome della variabile puntatore>;
I due operatori '*' di referenziazione' e'&' di dereferenziazione' possono essere visti come complementari.
Quest'ultimo, applicato a qualunque variabile, permette di riferirsi all'indirizzo del primo elemento di cui la variabile si compone.
    1. Redigere e compilare un programma con le seguenti istruzioni:
      #include <stdio.h>
      
      main(){
        int n;
        int *p;
        printf(" &p=%lX,  p=%lX,  *p=%d, \n n=%d,  &n=%lX,",&p,p,*p,n,&n);
        n=100;
        printf("\n\n &p=%lX,  p=%lX,  *p=%d, \n n=%d,  &n=%lX,",&p,p,*p,n,&n);
        p=&n;
        printf("\n\n &p=%lX,  p=%lX,  *p=%d, \n n=%d,  &n=%lX,",&p,p,*p,n,&n);
        *p=200;
        printf("\n\n &p=%lX,  p=%lX,  *p=%d, \n n=%d,  &n=%lX.",&p,p,*p,n,&n);
      } 
      
    2. fare anche il watch delle espressioni &p, p, *p, n, &n ed eseguire con Debug|Step over [F8] ,
    3. aggiungere nel watch anche le espressioni *&p, &*p, *&n ed eseguire con Debug|Step over [F8] ,

     
    1. Analizzare, compilare ed eseguire il seguente programma che fa uso di puntatori come argomenti di una funzione che realizza lo scambio tra due variabili:
      #include <stdio.h>
      
      
      void  scambio(int *x, int *y  ) {
          int temp;
          temp = *x; *x = *y; *y =temp;
      }
      
      
      main() {
        int a,b;
        printf("a = "); scanf("%d",&a);
        printf("b = "); scanf("%d",&b);
        scambio(&a,&b);
        printf("\n  a = %d,   b = %d",a,b);
      }
      

 
 

Aritmetica dei puntatori


 
    1. Redigere e compilare un programma con le seguenti istruzioni:
        int n;
        int *p;
        n=100;
        p=&n;
        n=200;
        (*p)++;
        p++;
        p=&n;
      
    2. fare il watch delle espressioni &n, n, &p, p, *p ed eseguire con Debug|Step over [F8] ,

     
    1. Analizzare, compilare ed eseguire il seguente programma per vedere come l'aritmetica dei puntatori dipenda dal tipo della variabile puntata.
      
      #include <stdio.h>
      
      main(){
      // viene assegnato un indirizzo, in esadecimale, alla variabile puntatore:
      	char *charp = (char *) 0x0111;    
      	int *intp = (int *) 0x0222;
      	printf("charp: %lX,   intp: %lX\n",charp, intp);
      //le variabili puntatore sono incrementate di 1:
      	printf("charp: %lX,   intp: %lX\n",charp+1, intp+1);
      }
      
    2. fare il watch di charp e intp
    3. modificare il programma cambiando i tipi di variabile puntata in modo da ritrovare quanto spazio di memoria Ŕ riservato ad altri tipi di dato semplice.

     
    1. Analizzare, compilare ed eseguire il seguente programma per il confronto tra puntatori
      #include <stdio.h>
      
      main() {
        int *p, *q;
        int m,n;
        printf("*p = ");
        scanf("%d",&m);
        p=&m;
        printf("*q = ");
        scanf("%d",&n);
        q=&n;
        printf("\n*p=%d   p=%lX  &p=%lX,\n  *q=%d    q=%lX   &q=%lX\n\n",*p,p,&p,*q,q,&q);
        if(p != q){
      	 if (*p==*q)
      		*p=*q+1;
      	 else
      		q=p;
      	 printf("*p=%d   p=%lX  &p=%lX,\n  *q=%d    q=%lX   &q=%lX\n\n",*p,p,&p,*q,q,&q);
        }
      }
      

 
 

Array e puntatori

  1. La stretta parentela tra array e puntatori emerge analizzando il programma seguente
    
    #include <stdio.h>
    
    void main(){
    	int s[5];
    	int *p;	
    	p=s;
    	for (int i=0; i<5; i++){
    		*(p+i)=i;
    	}
    	for (int i=0; i<=5; i++){
    		printf("%d ",s[i]);
    	}
    	printf("\n");
    	for (int i=0; i<5; i++){
    		s[i]=i+5;
    	}
    	for (int i=0; i<5; i++){
    		printf("%d ",p[i]);
    	}
    	printf("\n");
    	for (int i=0; i<5; i++){
    		*(p++) += 5;
    	}
    	for (int i=0; i<5; i++){
    		printf("%d ",s[i]);
    	}
    	p=s;
    	printf("\n");
    	for ( ; p<&s[4]+2; p++){
    		printf("%d ",*p);
    	}
    
    }
    
    Occore quindi fare attenzione nell'uso di vettori, puntatori e anche stringhe: C non fa nessun controllo sulle dimensioni. Col valore sbagliato di un indice, oltre la dimensione riservata nella dichiarazione, vengono sporcate aree contigue in memoria.

    Al contrario di un array o di una matrice che occupa in memoria lo spazio necessario per tutti gli elementi, un puntatore occupa solo lo spazio atto a contenere l'indirizzo del primo elemento.

  2. I puntatori sono necessari per scrivere moduli che abbiano per argomento array. Utilizzare la seguente function che determina la lunghezza di una stringa per scrivere un'altra function che restituisca l'ultimo elemento di una stringa
    int strLen(char *s){
    	int lungh=0;
    	while (*s++)
    		lungh ++;
    	return lungh;
    }
    

 
  NOTA: Al termine di ogni sessione di lavoro fare una copia del floppy e poi spegnere il computer con Start/Chiudi sessione/Arresta il sistema.
pagine di Roberto Ricci L.S. "A. Righi", Bologna. Ultima revisione