09 Record+puntatori
09 Record+puntatori
Esempio:
Si vuole rappresentare adeguatamente l'astrazione "contribuente",
caratterizzata dai seguenti attributi:
Nome,
Cognome,
Tipi di dato strutturato Reddito,
Aliquota
Con gli strumenti visti finora, per ogni contribuente necessario introdurre
Adrian Ailincai 2900 21.0 4 variabili:
Marco Albergamo 31000 27.0
Leonardo Amico 8000 21.0 char Nome[20], Cognome[20];
int Reddito;
Massimiliano Arpino 1500 19.2
float Aliquota;
1
typedef struct
Inizializzazione di record: Il costruttore struct pu essere utilizzato per dichiarare tipi non
primitivi basati sul record:
Dichiarazione di tipo strutturato record:
typedef struct {
possibile inizializzare i record in fase di definizione. <lista dichiarazioni campi>
} <id-tipo>;
Ad esempio: dove:
struct { char Nome[20], <lista definizioni campi> linsieme delle definizioni dei
campi componenti;
Cognome[20]; <id-tipo> lidentificatore del nuovo tipo.
int Reddito; Ad esempio: < lista
float Aliquota; typedef struct { char Nome[20], dichiarazione
Cognome[20]; campi >
} c1 ={"Valentina", "Florio", 7000+18000, 23.0 };
int Reddito;
float Aliquota;
} contribuente;
contribuente c1,c2,c3;
strcpy(c1.Nome, "Valentina"); < id-tipo >
...
Fondamenti di Informatica L-A Fondamenti di Informatica L-A
2
Esercizio sui record Vettori e record
switch (op) Non ci sono vincoli riguardo al tipo degli elementi di un vettore: si possono
proietta sullasse x realizzare anche vettori di record (strutture tabellari).
{ case 1: P.y= 0;break;
P x
case 2: proietta
P.x= 0;sullasse
break; y Ad esempio:
case 3: printf("%s","Traslazione?);y typedef struct { char Nome[20];
char Cognome[20];
scanf("%f%f",&Dx,&Dy);
int Reddito;
P.x=P.x+Dx;
calcola float Aliquota;
nuove
P.y=P.y+Dy; } Contribuente;
break;coordinate contribuente archivio[1000];
default: printf("errore!");
archivio un vettore di 1000 elementi, ciascuno dei quali di tipo
} contribuente
printf( "Nuove coordinate: abbiamo realizzato un vettore di record, o struttura tabellare.
coordinate
%f\t%f\n", P.x, P.y ); Nome Cognome Reddito Aliquota
} 0
999
Fondamenti di Informatica L-A Fondamenti di Informatica L-A
se
no
an
g io
na
na
char cognome[40];
na
ta_
ta_
ta_
data data_nasc;
Introduciamo un tipo di dato per rappresentare il generico studente:
da
da
da
} persona;
nome cognome data_nasc typedef struct { char nome[30];
persona P; char cognome[30];
int voto[3];
P.data_nasc.giorno=25; } studente;
P.data_nasc.mese=3;
P.data_nasc.anno=1992; La classe rappresentata da un vettore di studenti:
studente classe[20];
#include <stdio.h>
#define ita 0
#define mat 1
#define ing 2 /* continua.. stampa delle medie */
#define N 20 for( i=0; i<N; i++ ) // N studenti
typedef struct{ char nome[30], { for( m=0,j=ita; j<=ing; j++ ) // ita=0; ing=2
cognome[30]; m aggiorna il totale dei voti
+= classe[i].voto[j]; // m accumulatore
int voto[3]; printf( "media di %s %s: %f\n",
} studente; classe[i].nome,
media di <nome> classe[i].cognome,
<cognome>: <media> m/3 );
}
main() }
{ studente classe[N];
float m;
int i; int j;
/* lettura dati */
for(i=0;i<N; i++)
{ fflush(stdin);
nome i-mo studente
gets( classe[i].nome );
cognome i-mo studente );
gets( classe[i].cognome
for(j=ita; j<=ing; j++)
voto j-ma
scanf( "%d", materia i-mo studente
&classe[i].voto[j] );
}
Fondamenti di Informatica L-A Fondamenti di Informatica L-A
3
Il puntatore
un tipo di dato scalare, che consente di
rappresentare gli indirizzi delle variabili allocate in
memoria.
Puntatori
Dominio:
Il dominio di una variabile di tipo puntatore un
insieme di indirizzi: il valore di una variabile P di tipo
memoria puntatore pu essere lindirizzo di unaltra variabile
( variabile puntata ).
indirizzo di .. indirizzo di ..
P P
V V
puntatore puntatore
variabile puntata variabile puntata
Esempio Il puntatore in C
In C i puntatori si definiscono mediante il costruttore *.
indirizzo di ..
004f3abc dove:
P 004f3ac4 004f3ac0 <TipoElementoPuntato> e` il tipo della variabile puntata
puntatore 004f3ac4 V <NomePuntatore> e` il nome della variabile di tipo
004f3ac8 puntatore
variabile puntata
il simbolo * e` il costruttore del tipo puntatore.
004f3acc
004f3ad0
Ad esempio:
004f3ad4
int *P; /*P un puntatore a intero */
Esempio Il puntatore in C
Operatori:
Assegnamento (=): possibile l'assegnamento tra puntatori (dello stesso
tipo). disponibile la costante NULL, per indicare lindirizzo nullo (0).
Dereferencing (*) : un operatore unario. Si applica a un puntatore e
restituisce il valore contenuto nella cella puntata => serve per accedere alla
memoria variabile puntata.
Operatori aritmetici (vedi vettori e puntatori).
004f3ab8 Operatori relazionali:>,<,==, !=
004f3abc ?????
004f3ac4 P Operatore indirizzo &: si applica ad una variabile e restituisce lindirizzo
della cella di memoria nella quale allocata la variabile.
004f3ac0 ????? Q
004f3ac4 V Ad esempio:
25000 p1
int *p1, *p2;
004f3ac8 variabile puntata int A; A
004f3acc p2
int *P,*Q, p1 = &A;
004f3ad0 *p1 = 127;
V=25000; 004f3ad4
p2 = p1;
p1 = NULL;/* NULL la costante che vale 0 e
P=&V; denota il puntatore nullo */
4
Il puntatore in C Il puntatore in C
Operatori: Operatori:
Assegnamento (=): possibile l'assegnamento tra puntatori (dello stesso Assegnamento (=): possibile l'assegnamento tra puntatori (dello stesso
tipo). disponibile la costante NULL, per indicare lindirizzo nullo (0). tipo). disponibile la costante NULL, per indicare lindirizzo nullo (0).
Dereferencing (*) : un operatore unario. Si applica a un puntatore e Dereferencing (*) : un operatore unario. Si applica a un puntatore e
restituisce il valore contenuto nella cella puntata => serve per accedere alla restituisce il valore contenuto nella cella puntata => serve per accedere alla
variabile puntata. variabile puntata.
Operatori aritmetici (vedi vettori e puntatori). Operatori aritmetici (vedi vettori e puntatori).
Operatori relazionali:>,<,==, != Operatori relazionali:>,<,==, !=
Operatore indirizzo (&): si applica ad una variabile e restituisce lindirizzo Operatore indirizzo (&): si applica ad una variabile e restituisce lindirizzo
della cella di memoria nella quale allocata la variabile. della cella di memoria nella quale allocata la variabile.
Ad esempio: Ad esempio:
int *p1, *p2; p1 int *p1, *p2; p1
int A; A int A; 127 A
p2 p2
p1 = &A; p1 = &A;
*p1 = 127; *p1 = 127;
p2 = p1; p2 = p1;
p1 = NULL; p1 = NULL;
Il puntatore in C Il puntatore in C
Operatori: Operatori:
Assegnamento (=): possibile l'assegnamento tra puntatori (dello stesso Assegnamento (=): possibile l'assegnamento tra puntatori (dello stesso
tipo). disponibile la costante NULL, per indicare lindirizzo nullo (0). tipo). disponibile la costante NULL, per indicare lindirizzo nullo (0).
Dereferencing (*) : un operatore unario. Si applica a un puntatore e Dereferencing (*) : un operatore unario. Si applica a un puntatore e
restituisce il valore contenuto nella cella puntata => serve per accedere alla restituisce il valore contenuto nella cella puntata => serve per accedere alla
variabile puntata. variabile puntata.
Operatori aritmetici (vedi vettori e puntatori). Operatori aritmetici (vedi vettori e puntatori).
Operatori relazionali:>,<,==, != Operatori relazionali:>,<,==, !=
Operatore indirizzo (&): si applica ad una variabile e restituisce lindirizzo Operatore indirizzo (&): si applica ad una variabile e restituisce lindirizzo
della cella di memoria nella quale allocata la variabile. della cella di memoria nella quale allocata la variabile.
Ad esempio: Ad esempio:
int *p1, *p2; p1 int *p1, *p2; p1
int A; 127 A int A; 127 A
p2 p2
p1 = &A; p1 = &A;
*p1 = 127; *p1 = 127;
p2 = p1; p2 = p1;
p1 = NULL; p1 = NULL;
Ad esempio: Ad esempio:
float *p; p float *p; p
float R, A; A float R, A; A
5
Il puntatore in C: * e & Il puntatore in C: * e &
Operatore Indirizzo &: Operatore Indirizzo &:
& si applica solo ad oggetti che esistono in memoria (quindi, gia` & si applica solo ad oggetti che esistono in memoria (quindi, gia`
definiti). definiti).
& non e` applicabile ad espressioni. & non e` applicabile ad espressioni.
Ad esempio: Ad esempio:
float *p; p float *p; p
float R, A; A float R, A; 6.28 A
Dichiarazione di un tipo puntatore: il compilatore pu effettuare controlli statici sulluso dei puntatori.
Esempio:
typedef <TipoElementoPuntato> *<NomeTipo>;
typedef struct{int campo1; float campo2;}record;
int A, *p;
<TipoElementoPuntato> il tipo della variabile puntata
<NomePuntatore> il nome del tipo dichiarato.
record X, *q; X campo1 campo2
int float
p = &A;
Ad esempio: q = p; record
/* warning! */ q
typedef float *tpf;
q = &X; A
tpf p; int
*p = *q;
float f;
/* errore! */ p
p=&f;
*p=0.56; Viene segnalato dal compilatore (warning) il tentativo di utilizzo
congiunto di puntatori a tipi differenti.
Fondamenti di Informatica L-A Fondamenti di Informatica L-A
Variabili automatiche:
p Lallocazione e la deallocazione di variabili automatiche
effettuata automaticamente dal sistema (senza l'intervento del
programmatore).
*p
Ogni variabile automatica ha un nome, attraverso il quale la si
pu riferire.
Il programmatore non ha la possibilit di influire sul tempo di vita
di variabili automatiche.
6
Variabili automatiche Variabili dinamiche
Variabili dinamiche:
int *p, x; Le variabili dinamiche devono essere allocate e deallocate
esplicitamente dal programmatore.
struct {int a, b, c;} z, *w;
Larea di memoria in cui vengono allocate le variabili dinamiche si
chiama heap.
memoria Le variabili dinamiche non hanno un identificatore, ma possono
essere riferite soltanto attraverso il loro indirizzo (mediante i
x puntatori).
p Il tempo di vita delle variabili dinamiche e` l'intervallo di tempo che
z z.a intercorre tra l'allocazione e la deallocazione (che sono impartite
esplicitamente dal programmatore).
z.b
z.c
w
Variabili Dinamiche in C
Variabili dinamiche
variabili Il C prevede funzioni standard di allocazione e deallocazione
automatiche per variabili dinamiche:
int *p;
struct {int a, b, c;} *w; Allocazione: malloc
Deallocazione: free
memoria
heap
Significato:
La malloc
provoca la creazione di una variabile dinamica nellheap e
restituisce lindirizzo della variabile creata.
7
Variabili Dinamiche Variabili Dinamiche
Esempio: Esempio:
#include <stdlib.h> #include <stdlib.h>
typedef int *tp; typedef int *tp;
tp punt; tp punt;
... ...
punt=(tp )malloc(sizeof(int)); punt=(tp )malloc(sizeof(int));
heap heap
12
Variabili dinamiche
Puntatori e variabili dinamiche:
Deallocazione:
Si rilascia la memoria allocata dinamicamente con:
esempio
free(punt); #include <stdio.h>
8
Puntatori e variabili dinamiche: Puntatori e variabili dinamiche:
esempio esempio
#include <stdio.h> #include <stdio.h>
9
Problemi legati all'uso dei Puntatori Problemi legati all'uso dei Puntatori
3. Aliasing: 3. Aliasing:
Possibilita` di riferire la stessa variabile con puntatori diversi. Possibilita` di riferire la stessa variabile con puntatori diversi.
Ad esempio: Ad esempio:
int *p, *q; int *p, *q;
p=(int *)malloc(sizeof(int)); p=(int *)malloc(sizeof(int));
*p=3; heap *p=3; heap
q=p; /*p e q puntano alla stessa q=p; /*p e q puntano alla stessa
variabile */ variabile */
p p
*q = 10; /*anche *p e` cambiato! */ *q = 10; /*anche *p e` cambiato! */
3
q q
Problemi legati all'uso dei Puntatori Problemi legati all'uso dei Puntatori
3. Aliasing: 3. Aliasing:
Possibilita` di riferire la stessa variabile con puntatori diversi. Possibilita` di riferire la stessa variabile con puntatori diversi.
Ad esempio: Ad esempio:
int *p, *q; int *p, *q;
p=(int *)malloc(sizeof(int)); p=(int *)malloc(sizeof(int));
*p=3; heap *p=3; heap
q=p; /*p e q puntano alla stessa q=p; /*p e q puntano alla stessa
variabile */ variabile */
p p
*q = 10; /*anche *p e` cambiato! */ *q = 10; /*anche *p e` cambiato! */
3 10
q q
Ad esempio:
[typedef] TipoDato **TipoPunt; float V[10]; /*V una costante di tipo puntatore:
V equivale a &V[0];
V e` un puntatore (costante!) a float
Ad esempio: */
int x, *P, **DP; float *p;
P = &x; p=V; /* p punta a V[0] */
*p=0.15; /* equivale a V[0]=0.15 */
Dp = &P; V
**DP=1218; DP P x 0
1218
10
Operatori aritmetici su puntatori a
Vettori & Puntatori vettori
Nel linguaggio C, i vettori sono rappresentati mediante puntatori:
Nel linguaggio C, gli elementi di un vettore vengono allocati in memoria
il nome di una variabile di tipo vettore denota l'indirizzo del primo elemento in parole consecutive (cioe`, in celle fisicamente adiacenti), la cui
del vettore. dimensione dipende dal tipo dell'elemento.
Ad esempio:
float V[10]; /*V una costante di tipo puntatore: Conoscendo l'indirizzo del primo elemento e la dimensione
V equivale a &V[0]; dell'elemento, e` possibile calcolare l'indirizzo di qualunque elemento
V e` un puntatore (costante!) a float del vettore:
*/
float *p; Operatori aritmetici (somma e sottrazione) su puntatori a vettori:
p=V; /* p punta a V[0] */ Se V e W sono puntatori ad elementi di vettori ed i un intero:
*p=0.15; /* equivale a V[0]=0.15 */
V
(V+i) restituisce l'indirizzo dell'elemento spostato di i posizioni in avanti
rispetto a quello puntato da V;
0.15 0
(V-i) restituisce l'indirizzo dell'elemento spostato di i posizioni all'indietro
V = p; /*ERRORE! V un puntatore costante*/ rispetto a quello puntato da V;
(V-W) restituisce l'intero che rappresenta il numero di elementi
compresi tra V e W.
p
9
Fondamenti di Informatica L-A Fondamenti di Informatica L-A
11
Soluzione Esercizio
#include <stdio.h>
#include <stdlib.h>
typedef char parola[21]; /* ..Continua: stampa */
for(i=N-1; i>=0; i--)
main() { j=20;
{ parola w, *p; while( p[i][j] != '\0' ) {
int i, j, N; j--; posizionati sullultimo carattere della parola
}
printf("Quante parole? "); for( j-- stampa
; j>=0 in ordine
; j-- inverso
)
scanf("%d", &N); printf("%c",p[i][j]);
fflush(stdin); printf("\n");
/* allocazione del vettore */ }
p=(parola *)malloc(N*sizeof(parola)); /* deallocazione del vettore*/
/* lettura della sequenza */ free(p);
for(i=0; i<N; i++) }
gets(p[i]);
12