Il 0% ha trovato utile questo documento (0 voti)
156 visualizzazioni12 pagine

09 Record+puntatori

Il documento descrive il tipo di dato strutturato 'record' in C. Un record è un insieme di elementi non omogenei con un numero fisso di campi di tipo diverso. In C i record possono essere definiti usando la struttura 'struct', che consente di aggregare più attributi in un'unica astrazione. I campi di un record struct possono essere accessi e manipolati individualmente.

Caricato da

Giulia Schiesaro
Copyright
© © All Rights Reserved
Per noi i diritti sui contenuti sono una cosa seria. Se sospetti che questo contenuto sia tuo, rivendicalo qui.
Formati disponibili
Scarica in formato PDF, TXT o leggi online su Scribd
Il 0% ha trovato utile questo documento (0 voti)
156 visualizzazioni12 pagine

09 Record+puntatori

Il documento descrive il tipo di dato strutturato 'record' in C. Un record è un insieme di elementi non omogenei con un numero fisso di campi di tipo diverso. In C i record possono essere definiti usando la struttura 'struct', che consente di aggregare più attributi in un'unica astrazione. I campi di un record struct possono essere accessi e manipolati individualmente.

Caricato da

Giulia Schiesaro
Copyright
© © All Rights Reserved
Per noi i diritti sui contenuti sono una cosa seria. Se sospetti che questo contenuto sia tuo, rivendicalo qui.
Formati disponibili
Scarica in formato PDF, TXT o leggi online su Scribd
Sei sulla pagina 1/ 12

Il Record

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;

una soluzione scomoda e non astratta: le quattro variabili sono


indipendenti tra di loro.
Valerio Zerillo 45000 34.5
necessario un costrutto che consenta laggregazione dei 4 attributi
nell'astrazione contribuente: il record.

Fondamenti di Informatica L-A Fondamenti di Informatica L-A

Tipi strutturati: il Record Il Record in C: struct


Un record un insieme finito di elementi, in generale non omogeneo: Collezioni con un numero finito di campi (anche disomogenei) sono
il numero degli elementi rigidamente fissato a realizzabili in C mediante il costruttore di tipo strutturato struct.
priori.
gli elementi possono essere di tipo diverso.
il tipo di ciascun elemento componente (campo) prefissato. Definizione di variabile di tipo struct:
Ad esempio:
struct { struct {
NOME COGNOME REDDITO ALIQUOTA <lista def. campi> char Nome[20],
Cognome[20];
} <id-variabile>; int Reddito;
Formalmente:
Il record un tipo strutturato il cui dominio si ottiene mediante prodotto float Aliquota;
cartesiano: dove: } c1;
dati n insiemi, Ac1, Ac2, ..., Acn, il prodotto cartesiano tra essi:
Ac1 Ac2 ... Acn
<lista def. campi> linsieme delle definizioni dei campi componenti,
costruita usando le stesse regole sintattiche della definizione di variabili:
consente di definire un tipo di dato strutturato (il record) i cui elementi sono n-ple <tipo1> <campo1>; char Nome[20],
ordinate:
<tipo2> <campo2>; Cognome[20];
(ac1, ac2, ..., acn)
... int Reddito;
dove aciAci.
<tipoN> <campoN>; float Aliquota;
Ad esempio:
Il numero complesso pu essere definito attraverso il prodotto cartesiano R R.
<id-variabile> lidentificatore della variabile di tipo record cos definita.
Fondamenti di Informatica L-A Fondamenti di Informatica L-A

Il tipo struct Il tipo struct: assegnamento


Accesso ai campi:
Per accedere (e manipolare) i singoli campi di un struct {
record si usa la notazione postfissa : char Nome[20],
Cognome[20];
<id-variabile>.<componente> int Reddito;
strcpy(c1.Nome,Valentina);
indica il valore del campo <componente> della float Aliquota;
strcpy(c1.Cognome,Florio);
variabile <id-variabile> . } c1, c2;
c1.Reddito = 7000+18000;
c1.Aliquota = 23.0;

I singoli campi possono essere manipolati con gli Operatori:


c2=c1;
operatori previsti per il tipo ad essi associato.
struct {
Lunico operatore previsto per dati di tipo struct
char Nome[20],
c1.Nome
loperatore di assegnamento (=):
Cognome[20];
int Reddito;
float Aliquota;
} c1;
strcpy(c1.Nome,Valentina); possibile lassegnamento diretto tra record
strcpy(c1.Cognome,Florio);
c1.Reddito = 7000+18000; di tipo equivalente.
c1.Aliquota = 23.0;
Fondamenti di Informatica L-A Fondamenti di Informatica L-A

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

typedef struct Il tipo struct in sintesi


Riassumendo, la sintassi da adottare :
Nota: non consentito definire due tipi diversi con lo stesso nome. [typedef] struct {
Per possibile che un campo del record abbia lo stesso nome di <tipo-1> <nome_campo-1>;
una variabile. Come Reddito, nellesempio:
<tipo-2> <nome_campo-2>;
...
typedef struct { char Nome[20]; <tipo-N> <nome-campo-N>;
char Cognome[20]; } <nome>;
int Reddito; Vincoli:
float Aliquota; <nome-campo-i> un identificatore stabilito che individua il campo i-
} contribuente; esimo;
<tipo-i> un qualsiasi tipo, semplice o strutturato.
contribuente c1, c2, c3;
<nome> lidentificatore della struttura (o del tipo, se si usa typedef)
unsigned int Reddito = 7000; Uso:
la struttura una collezione di un numero fissato di elementi di vario
c1.Reddito = Reddito + 18000; tipo (<tipo-campo-i>);
il singolo campo <nome-campo-i> di un record R individuato
variabile.campo variabile mediante la notazione: R.<nome-campo-i>;
(variabile strutturata) (intero senza segno) se due strutture di dati di tipo struct hanno lo stesso tipo, allora
possibile lassegnamento diretto.
Fondamenti di Informatica L-A Fondamenti di Informatica L-A

Esercizio sui record Esercizio sui record


#include <stdio.h>
Realizzare un programma che, lette da input le main() P x
coordinate di un punto P del piano, sia in grado di { typedef struct{float x,y;} punto;
y
applicare a P alcune trasformazioni geometriche punto P;
(traslazione, e proiezioni sui due assi). unsigned int op;
float Dx, Dy;
/* lettura delle coordinate da input in P: */
Rappresentiamo il punto del piano cartesiano printf("ascissa? ");
mediante una struct di due campi (float), ciascuno scanf("%f",&P.x);
associato a una particolare coordinata: printf("ordinata? ");
scanf("%f",&P.y);
typedef struct{ float x; P x /* lettura dell'operazione richiesta assumendo le
float y; y convenzioni:
} punto; 0: termina
1: proietta sull'asse x
punto P; /* P una variabile di tipo punto */ 2: proietta sull'asse y
3: trasla di Dx, Dy */
printf("%s\n","operazione(0,1,2,3)?");
scanf("%d",&op);

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

Vettori e Record Esercizio


Allo stesso modo, si possono fare record di vettori e record di record.
Scrivere un programma che acquisisca i dati relativi agli studenti di una
Ad esempio: classe:
nome
typedef struct{ int giorno; cognome
int mese; voti: rappresenta i voti dello studente in 3 materie (italiano, matematica,
int anno; inglese);
} data giorno mese anno
rno

se

no

Il programma deve successivamente calcolare e stampare, per ogni


me

an
g io

studente, la media dei voti ottenuti nelle 3 materie.


sc.

typedef struct{ char nome[20];


sc.
sc.

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

Fondamenti di Informatica L-A Fondamenti di Informatica L-A

#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

Fondamenti di Informatica L-A Fondamenti di Informatica L-A

Esempio Il puntatore in C
In C i puntatori si definiscono mediante il costruttore *.

Definizione di una variabile puntatore:


memoria
<TipoElementoPuntato> *<NomePuntatore>;
004f3ab8

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 */

Fondamenti di Informatica L-A Fondamenti di Informatica L-A

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 */

Fondamenti di Informatica L-A Fondamenti di Informatica L-A

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;

Fondamenti di Informatica L-A Fondamenti di Informatica L-A

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;

Fondamenti di Informatica L-A Fondamenti di Informatica L-A

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.

Operatore Dereferencing *: Operatore Dereferencing *:


consente di accedere ad una variabile specificandone l'indirizzo consente di accedere ad una variabile specificandone l'indirizzo
l'indirizzo rappresenta un modo alternativo al nome (alias) per l'indirizzo rappresenta un modo alternativo al nome (alias) per
accedere e manipolare la variabile: accedere e manipolare la variabile:

Ad esempio: Ad esempio:
float *p; p float *p; p
float R, A; A float R, A; A

p=&A; /* *p un alias di A*/ R p=&A; /* *p un alias di A*/ R


R=2; R=2;
*p=3.14*R; /* A modificato */ *p=3.14*R; /* A modificato */

Fondamenti di Informatica L-A Fondamenti di Informatica L-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.

Operatore Dereferencing *: Operatore Dereferencing *:


consente di accedere ad una variabile specificandone l'indirizzo consente di accedere ad una variabile specificandone l'indirizzo
l'indirizzo rappresenta un modo alternativo al nome (alias) per l'indirizzo rappresenta un modo alternativo al nome (alias) per
accedere e manipolare la variabile: accedere e manipolare la variabile:

Ad esempio: Ad esempio:
float *p; p float *p; p
float R, A; A float R, A; 6.28 A

p=&A; /* *p un alias di A*/ 2 R p=&A; /* *p un alias di A*/ 2 R


R=2; R=2;
*p=3.14*R; /* A modificato */ *p=3.14*R; /* A modificato */

Fondamenti di Informatica L-A Fondamenti di Informatica L-A

Puntatore come costruttore di tipo Puntatori: controlli di tipo


Il costruttore di tipo "*" pu essere anche usato per dichiarare Nella definizione di un puntatore necessario indicare il tipo della
tipi non primitivi basati sul puntatore. variabile puntata.

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 e dinamiche


In C possibile classificare le variabili in base al loro tempo di vita.

Variabili dinamiche Due categorie:


variabili automatiche
variabili dinamiche
heap

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.

tutte le variabili viste finora rientrano nella categoria delle


variabili automatiche.

Fondamenti di Informatica L-A Fondamenti di Informatica L-A

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

Fondamenti di Informatica L-A Fondamenti di Informatica L-A

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

malloc e free sono definite a livello di sistema operativo,


*p variabili
mediante la libreria standard <stdlib.h> (da includere nei
dinamiche
p programmi che le usano).
*w
z.a z.b z.c
w

Fondamenti di Informatica L-A Fondamenti di Informatica L-A

Variabili Dinamiche Variabili Dinamiche


Allocazione di variabili dinamiche:
La memoria dinamica viene allocata con la funzione standard
malloc. La sintassi da usare e`:
Esempio:
#include <stdlib.h>
punt = (tipodato *)malloc(sizeof(tipodato)); typedef int *tp;
tp punt;
dove: ...
tipodato e` il tipo della variabile puntata
punt e` una variabile di tipo tipodato *
punt=(tp )malloc(sizeof(int));
sizeof() e` una funzione standard che calcola il numero di byte che heap
occupa il dato specificato come argomento
e` necessario convertire esplicitamente il tipo del valore ritornato (casting ):
(tipodato *) malloc(..) *punt=12; punt

Significato:
La malloc
provoca la creazione di una variabile dinamica nellheap e
restituisce lindirizzo della variabile creata.

Fondamenti di Informatica L-A Fondamenti di Informatica L-A

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

*punt=12; punt *punt=12; punt

12

Fondamenti di Informatica L-A Fondamenti di Informatica L-A

Variabili dinamiche
Puntatori e variabili dinamiche:
Deallocazione:
Si rilascia la memoria allocata dinamicamente con:
esempio
free(punt); #include <stdio.h>

dove punt e` l'indirizzo della variabile da deallocare. main() heap


{ int *P, *Q, x, y;
Dopo questa operazione, la cella di memoria occupata da *punt viene liberata: x=5; Q
*punt non esiste piu`. P
heap y=14;
P=(int *)malloc(sizeof(int));
Esempio:
#include <stdlib.h> Q=(int *)malloc(sizeof(int));
punt *P = 25; x
typedef int *tp;
tp punt; *Q = 30;
... *P = x; y
punt=(tp )malloc(sizeof(int)); y = *Q;
*punt=12; P = &x;
...<uso di punt>... }
free(punt);

Fondamenti di Informatica L-A Fondamenti di Informatica L-A

Puntatori e variabili dinamiche: Puntatori e variabili dinamiche:


esempio esempio
#include <stdio.h> #include <stdio.h>

main() heap main() heap


{ int *P, *Q, x, y; { int *P, *Q, x, y;
x=5; P Q x=5; P Q
y=14; y=14;
P=(int *)malloc(sizeof(int)); P=(int *)malloc(sizeof(int));
Q=(int *)malloc(sizeof(int)); Q=(int *)malloc(sizeof(int));
*P = 25; x 5 *P = 25; x 5
*Q = 30; *Q = 30;
*P = x; y 14 *P = x; y 14
y = *Q; y = *Q;
P = &x; P = &x;
} }

Fondamenti di Informatica L-A Fondamenti di Informatica L-A

8
Puntatori e variabili dinamiche: Puntatori e variabili dinamiche:
esempio esempio
#include <stdio.h> #include <stdio.h>

main() heap main() heap


{ int *P, *Q, x, y; { int *P, *Q, x, y;
x=5; P Q x=5; P Q 30
y=14; y=14;
P=(int *)malloc(sizeof(int)); 25 P=(int *)malloc(sizeof(int)); 25
Q=(int *)malloc(sizeof(int)); Q=(int *)malloc(sizeof(int));
*P = 25; x 5 *P = 25; x 5
*Q = 30; *Q = 30;
*P = x; y 14 *P = x; y 14
y = *Q; y = *Q;
P = &x; P = &x;
} }

Fondamenti di Informatica L-A Fondamenti di Informatica L-A

Puntatori e variabili dinamiche: Puntatori e variabili dinamiche:


esempio esempio
#include <stdio.h> #include <stdio.h>

main() heap main() heap


{ int *P, *Q, x, y; { int *P, *Q, x, y;
x=5; P Q 30 x=5; P Q 30
y=14; y=14;
P=(int *)malloc(sizeof(int)); 5 P=(int *)malloc(sizeof(int)); 5
Q=(int *)malloc(sizeof(int)); Q=(int *)malloc(sizeof(int));
*P = 25; x 5 *P = 25; x 5
*Q = 30; *Q = 30;
*P = x; y 14 *P = x; y 30
y = *Q; y = *Q;
P = &x; P = &x;
} }

Fondamenti di Informatica L-A Fondamenti di Informatica L-A

Puntatori e variabili dinamiche: Problemi legati all'uso dei Puntatori


esempio 1. Aree inutilizzabili:
Possibilit di perdere l'indirizzo di aree di memoria allocate al
#include <stdio.h> programma che quindi non sono pi accessibili. (v. esempio
precedente).
main() heap
{ int *P, *Q, x, y; 2. Riferimenti pendenti (dangling references):
Possibilit di fare riferimento ad aree di memoria non pi allocate.
x=5; P Q 30
y=14;
P=(int *)malloc(sizeof(int)); 5
Ad esempio: heap
Q=(int *)malloc(sizeof(int));
*P = 25; x 5 int *P;
P = (int *) malloc(sizeof(int));
*Q = 30; ... P
*P = x; y 30 free(P);
y = *Q; *P = 100; /* Da non fare! */
P = &x;
}

l'ultimo assegnamento ha come effetto collaterale la perdita dell'indirizzo di una variabile


dinamica (quella precedentemente referenziata da P) che rimane allocata ma non pi
utilizzabile!

Fondamenti di Informatica L-A Fondamenti di Informatica L-A area


deallocata

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

Fondamenti di Informatica L-A Fondamenti di Informatica L-A

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

Fondamenti di Informatica L-A Fondamenti di Informatica L-A

Puntatori a puntatori Vettori & Puntatori


Nel linguaggio C, i vettori sono rappresentati mediante puntatori:
Un puntatore pu puntare a variabili di tipo qualunque (semplici
o strutturate): il nome di una variabile di tipo vettore denota l'indirizzo del primo elemento
pu puntare anche a un puntatore: del vettore.

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

DP un doppio puntatore (o handle): dereferenziando 2 volte


DP, si accede alla variabile puntata dalla "catena" di riferimenti. p
9
Fondamenti di Informatica L-A Fondamenti di Informatica L-A

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

Operatori aritmetici su puntatori a Vettori e Puntatori


vettori Durante l'esecuzione di ogni programma C, ogni riferimento ad un elemento di

un vettore tradotto in un puntatore dereferenziato; per esempio:


Esempio:
#include <stdio.h> V[0] viene tradotto in *(V)
V[1] viene tradotto in *(V + 1)
V[i] viene tradotto in *(V + i)
main() V[expr] viene tradotto in *(V + expr)
{ float V[8]={1.1,2.2,3.3,4.4,5.5,6.6,7.7,8.8};
int k; V Esempio:
float *p, *q; #include <stdio.h>
1.1 0
p=V+7; main ()
2.2
q=p-2; { char a[ ] = "0123456789"; /* a un vettore di 10 char */
k 2 3.3 int i = 5;
k=p-q;
printf("%c%c%c%c%c\n",a[i],a[5],i[a],5[a],(i-1)[a]); /* !!! */
printf("%f,\t%f,\t%d\n",*p, *q, k); 4.4
}
} 5.5
q
6.6 5 Stampa: 55554
Stampa: 8.8, 6.6, 2 7.7
NB: Per il compilatore a[i] e i[a] sono lo stesso elemento, perch viene sempre
8.8 7 eseguita la conversione: a[i] =>*(a+i) (senza eseguire alcun controllo n su a,
p n su i).

Fondamenti di Informatica L-A Fondamenti di Informatica L-A

Complementi sui puntatori


Esercizio
Vettori di puntatori:
Il costruttore [ ] ha precedenza rispetto al costruttore *. Quindi: Si vuole realizzare un programma che, data da input una
char *a[10]; equivale a char *(a[10]); sequenza di N parole (ognuna, al massimo, di 20 caratteri),
stampi in ordine inverso le parole date, ognuna "ribaltata"
a un vettore di 10 puntatori a carattere. (cio, stampando i caratteri in ordine inverso: dall'ultimo al
NB: Per un puntatore ad un vettore di caratteri necessario forzare la precedenza (con le primo). Si supponga che N non sia noto a priori, ma venga
parentesi): char (* a) [10]; fornito da input. Utilizzare una struttura dinamica.
Puntatori a strutture:
E' possibile utilizzare i puntatori per accedere a variabili di tipo struct, tenendo conto che Progetto dei dati.
il punto della notazione postfissa ha la precedenza sull'operatore di dereferencing *. Memorizziamo le parole in un vettore di N. stringhe che verra`
Esempio: allocato dinamicamente.
typedef struct{ int Campo_1,Campo_2; } TipoDato;
TipoDato S, *P; typedef char parola[21];
P = &S;
/* tipo associato alla singola parola */
(*P).Campo1=75; /* assegnamento della costante 75 al Campo1 della
struct puntata da P* (e` necessario usare le parola *p;
parentesi) */ /* puntatore per l'accesso
Operatore ->:
al vettore delle parole */
L'operatore -> consente di accedere ad un campo di una struttura referenziata da un
puntatore in modo pi sintetico:
P->Campo1=75;

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]);

Fondamenti di Informatica L-A Fondamenti di Informatica L-A

12

Potrebbero piacerti anche