1 Array e puntatori Corso di Informatica A Vito Perrone
Copyright © The McGraw-Hill Companies, srl 2 Strutture di controllo in C Informatica A – V. Perrone Indice Tipi di dati strutturati: Array Puntatori Tipi di dati strutturati: Array Esempio
Copyright © The McGraw-Hill Companies, srl 3 Strutture di controllo in C Informatica A – V. Perrone I tipi strutturati: 1. Il costruttore array Definizione del nuovo tipo anArray: typedefintanArray[20]; dichiazione di variabili di tipo anArray: anArraylista1, lista2; La dichiarazione: intlista[20]; Va perciò interpretata come unabbreviazione per: typedefintarrayAnonimo[20]; arrayAnonimo lista;
Copyright © The McGraw-Hill Companies, srl 4 Strutture di controllo in C Informatica A – V. Perrone Dichiarazione mediante nuovo tipo: typedef doubleVettoreDiReali[20]; VettoreDiRealiv1, v2, v3; Più semplice e altrettanto chiara: doublev1[20], v2[20], v3[20]; Dichiarazione mediante nuovi tipi: typedefdoublePioggeMensili[12]; typedefdoubleIndiciBorsa[12]; PioggeMensiliPiogge01, Piogge02, Piogge03; IndiciBorsaIndici01, Indici02, Indici03; Preferibile a: doublePiogge01[12], Piogge02[12], Piogge03[12], Indici01[12], Indici02[12], Indici03[12]; Quando esplicitare il nome del tipo?
Copyright © The McGraw-Hill Companies, srl 5 Strutture di controllo in C Informatica A – V. Perrone E possibile definire un array di array (una matrice): typedefintVettore[20]; typedefVettoreMatriceIntera20Per20[20]; MatriceIntera20Per20matrice1; Oppure, più brevemente: typedefintMatriceIntera20Per20[20][20]; MatriceIntera20Per20matrice1; Anche una matrice può essere definita in modo abbreviato: intmatrice1[20][20]; E possibile definire array di array di array…: intmatriceTridimensionale1[10][20][30]; Per accedere agli elementi di matriceTridimensionale1 : matriceTridimensionale1[2][8][15] coloreListaColori[10]; Matrici
Copyright © The McGraw-Hill Companies, srl 6 Strutture di controllo in C Informatica A – V. Perrone Dimensione degli array Un array ha dimensioni fisse minor flessibilità del linguaggio typedefcharString[30]; StringNome, Cognome; Parole corte provocano spreco di memoria (fisica) Parole lunghe: dovremmo anche prevedere istruzioni del tipo: if (LunghezzaParola == 30) printf("Parola troppo lunga"); Perché? Principio dellallocazione statica della memoria.
Copyright © The McGraw-Hill Companies, srl 7 Strutture di controllo in C Informatica A – V. Perrone Un parziale rimedio (1) /* Programma InvertiSequenza */ #include main() { intContatore; intMemorizzazione[100]; Contatore = 0; while (Contatore < 100) /* si ricordi che il valore dell'indice di un array di 100 elementi varia da 0 a 99 */ { scanf("%d", &Memorizzazione[Contatore]); Contatore = Contatore + 1; } …
Copyright © The McGraw-Hill Companies, srl 8 Strutture di controllo in C Informatica A – V. Perrone /* Programma InvertiSequenza (continuazione) */ … Contatore = Contatore – 1; while (Contatore >= 0) { printf("%d\n", Memorizzazione[Contatore]); Contatore = Contatore – 1; } E se invece di 100 la sequenza fosse lunga 1000? Un parziale rimedio (2)
Copyright © The McGraw-Hill Companies, srl 9 Strutture di controllo in C Informatica A – V. Perrone /* Program InvertiSequenza */ #include #define LunghezzaSequenza 100 main() { intContatore; intMemorizzazione[LunghezzaSequenza]; Contatore = 0; while (Contatore < LunghezzaSequenza) { scanf("%d", &Memorizzazione[Contatore]); Contatore = Contatore + 1; } … Un parziale rimedio (3)
Copyright © The McGraw-Hill Companies, srl 10 Strutture di controllo in C Informatica A – V. Perrone /* Program InvertiSequenza (continuazione) */ … Contatore = Contatore – 1; while (Contatore >= 0) { printf("%d\n", Memorizzazione[Contatore]); Contatore = Contatore – 1; } NB: la stessa cosa non si poteva fare con la dichiarazione const Un parziale rimedio (4)
Copyright © The McGraw-Hill Companies, srl 11 Strutture di controllo in C Informatica A – V. Perrone Assegnamento tra array: attenzione! Dati i seguenti array: typedefintanArray[10]; anArrayArray1, Array2; Listruzione: Array2 = Array1; E scorretta! Sarà necessaria unistruzione ciclica che scorra i singoli elementi dellarray –i = 0; while (i < 10) array2[i] = array1[i]; Capiremo il perché in seguito
Copyright © The McGraw-Hill Companies, srl 12 Strutture di controllo in C Informatica A – V. Perrone #include #define LunghezzaArray 50 main() { inti, j, k; charTempCar; charArray1[LunghezzaArray], Array2[LunghezzaArray]; /* Nella seguente dichiarazione il valore LunghezzaArray]*2 è un valore costante calcolato a tempo di compilazione */ charArrayConc[LunghezzaArray*2]; /* Legge la prima stringa assicurandosi che essa non superi la dimensione dell'array, 50 caratteri /* i = 0; while (i < LunghezzaArray) /* Si ricordi che il valore dell'indice di un array di LunghezzaArray elementi è compreso fra 0 e LunghezzaArray–1 */ { scanf("%c", &TempCar); Array1[i] = TempCar; i = i + 1; } … Programma concatenazione stringhe (1)
Copyright © The McGraw-Hill Companies, srl 13 Strutture di controllo in C Informatica A – V. Perrone … /* Legge la seconda stringa assicurandosi che essa non superi la dimensione dell'array, 50 caratteri /* i = 0; while (i < LunghezzaArray) { scanf("%c%, &TempCar); Array2[i] = TempCar; i = i + 1; } /* Confronta le due stringhe per capire quale precede l'altra in ordine alfabetico */ i = 0; while (i < LunghezzaArray && Array1[i] == Array2[i]) i = i+1; if(i == LunghezzaArray || Array1[i] < Array2[i]) /* Le due stringhe sono uguali o la prima precede la seconda in ordine alfabetico */ … Programma concatenazione stringhe (2)
Copyright © The McGraw-Hill Companies, srl 14 Strutture di controllo in C Informatica A – V. Perrone … /* Le due stringhe sono uguali o la prima precede la seconda in ordine alfabetico */ { k = 0; j = 0; while (j < LunghezzaArray) { ArrayConc[k] = Array1[j]; k = k + 1; j = j + 1; } j = 0; while (j < LunghezzaArray) { ArrayConc[k] = Array2[j]; k = k + 1; j = j + 1; } else … Programma concatenazione stringhe (3)
Copyright © The McGraw-Hill Companies, srl 15 Strutture di controllo in C Informatica A – V. Perrone … /* Se la seconda stringa precede la prima in ordine alfabetico, ossia se (Array2[i] < Array1[i]) */ { k = 0; j = 0; while (j < LunghezzaArray) { ArrayConc[k] = Array2[j]; k = k + 1; j = j + 1; } j = 0; while (j < LunghezzaArray) { ArrayConc[k] = Array1[j]; k = k + 1; j = j + 1; } /* Stampa la stringa ottenuta dalla concatenazione */ k = 0; while (k < (LunghezzaArray*2)) {printf("%c", ArrayConc[k]); k = k + 1;} } Programma concatenazione stringhe (4)
Copyright © The McGraw-Hill Companies, srl 16 Strutture di controllo in C Informatica A – V. Perrone La dichiarazione: int a[100]; alloca memoria per 100 elementi interi, a partire da un certo indirizzo di memoria scelto dal calcolatore n.b. il numero degli elementi dellarray e la dimensione del tipo base devono essere noti al compilatore Per accedere a un elemento dellarray a Si calcola il valore dellindice (può essere una espressione qualsiasi purchè produca un risultato di tipo integral) Si somma il valore calcolato moltiplicato per la dimensione (in byte) del tipo base allindirizzo della prima cella dellarray Esempio: Supponendo che larray a sia allocato a partire dal byte in memoria. Lelemento a[3] corrisponde allindirizzo *dimInt = supponendo che un int sia rappresentato con 32 bit (4 byte) Importante: non viene fatto alcun controllo sul rispetto dei limiti dellarray (Tipico errore) Alcune precisazioni sugli array 1/2
Copyright © The McGraw-Hill Companies, srl 17 Strutture di controllo in C Informatica A – V. Perrone Alcune precisazioni sugli array 2/2 Le stringhe in C sono array di caratteri terminate dal carattere speciale \0 Esempio: char parola[20]; scanf(%s, parola); /* si noti lassenza del & */ printf(%c, parola[0]); Esercizio: …..
Copyright © The McGraw-Hill Companies, srl 18 Strutture di controllo in C Informatica A – V. Perrone Il costruttore puntatore (1) Dichiarazione di una variabile puntatore: typedefTipoDato*TipoPuntatore; Dereferenziazione: *P indica la cella di memoria il cui indirizzo è contenuto in P typedefTipoDato*TipoPuntatore; TipoPuntatoreP; TipoDatox; P Valore di tipo TipoDato
Copyright © The McGraw-Hill Companies, srl 19 Strutture di controllo in C Informatica A – V. Perrone Il costruttore puntatore (2) Loperatore unario & significa indirizzo di ed è il duale delloperatore *. typedefTipoDato*TipoPuntatore; TipoPuntatoreP, Q; TipoDatoy, z; P = &y; Q = &z; P = Q; y e z sono di tipo TipoDato mentre P e Q sono puntatori a variabili di tipo TipoDato.
Copyright © The McGraw-Hill Companies, srl 20 Strutture di controllo in C Informatica A – V. Perrone *P = x; P 23 x Esempi (1) P x P = 14; x = 23;
Copyright © The McGraw-Hill Companies, srl 21 Strutture di controllo in C Informatica A – V. Perrone P x P x x = *P; Esempi (2)
Copyright © The McGraw-Hill Companies, srl 22 Strutture di controllo in C Informatica A – V. Perrone P = &y; P 14 y Q = &z; Q 23 z Attenzione: è vero che P = Q; *P = *Q; ?? Esempi (3) P = Q;
Copyright © The McGraw-Hill Companies, srl 23 Strutture di controllo in C Informatica A – V. Perrone typedefTipoDato*TipoPuntatore; typedefAltroTipoDato*AltroTipoPuntatore; TipoDato*Puntatore; TipoDato**DoppioPuntatore; TipoPuntatoreP, Q; AltroTipoPuntatoreP1, Q1; TipoDatox, y; AltroTipoDatoz, w; istruzioni corrette:istruzioni scorrette : Puntatore = &y; P1 = P; (warning) DoppioPuntatore = &P; w = *P; (error) Q1 = &z; *DoppioPuntatore = y; (warning) P = &x; Puntatore = DoppioPuntatore; (warning) P = Q; *P1 = *Q; (error) *P = *Q; *Puntatore = x; P = *DoppioPuntatore; z = *P1; Puntatore = P; Puntatori e tipi
Copyright © The McGraw-Hill Companies, srl 24 Strutture di controllo in C Informatica A – V. Perrone Il valore iniziale di un puntatore dovrebbe essere NULL NULL significa che non si riferisce ad alcuna cella di memoria Dereferenziando NULL si ha un errore in esecuzione Non fare MAI affidamento sulle inizializzazioni implicite delle variabili che C potrebbe fare (alcune implementazioni lo fanno a NULL, molte altre no) Valore iniziale di un puntatore
Copyright © The McGraw-Hill Companies, srl 25 Strutture di controllo in C Informatica A – V. Perrone C permette operazioni di somma e sottrazione tra puntatori Il valore viene incrementato di un multiplo dellingombro (sizeof) del tipo puntato Esempio: int i; IntRef p = &i; p = p + 5; Se supponiamo che i sia allocata alla cella 1000 allora lassegnamento p = &i assegna a p il valore 1000 e lassegnamento p = p + 5 assegna a p il valore 1020 (si suppone che sizeof(int) sia 4) Aritmetica tra puntatori 1/3
Copyright © The McGraw-Hill Companies, srl 26 Strutture di controllo in C Informatica A – V. Perrone Sia: int a[5]; int i; int * p; Allora: – a[i] è equivalente a *(a+i) – p = a è equivalente a p = &a[0] – p = a+1 è equivalente a p = &a[1] – a = p errore, a è puntatore costante – a = a + 1 errore, a è puntatore costante – p = p + 1 corretto Aritmetica tra puntatori 2/3
Copyright © The McGraw-Hill Companies, srl 27 Strutture di controllo in C Informatica A – V. Perrone Se p e q puntano a due diversi elementi di un array p – q dà la distanza nellarray tra gli elementi puntati Questo in generale non coincide con la differenza aritmetica tra il valore dei puntatori Esempio: Se p e q sono puntatori a int e sizeof(int) è 4 e p è 1000 e q è 1040 allora: p – q è 10 e non 40 Aritmetica tra puntatori 3/3
Copyright © The McGraw-Hill Companies, srl 28 Strutture di controllo in C Informatica A – V. Perrone Array e puntatori (1) Loperatore sizeof produce il numero di byte occupati da ciascun elemento di un array o da un array nel suo complesso. Se si usano quattro byte per la memorizzazione di un valore int : inta[5]; Allora: sizeof(a[2]) Restituisce il valore 4 e: sizeof(a) Restituisce il valore 20. Il nome di una variabile di tipo array viene considerato in C come lindirizzo della prima parola di memoria che contiene il primo elemento della variabile di tipo array (lo 0-esimo …). Se ne deduce: a punta a una parola di memoria esattamente come un puntatore; a punta sempre al primo elemento della variabile di tipo array (è un puntatore fisso al quale non è possibile assegnare lindirizzo di unaltra parola di memoria).
Copyright © The McGraw-Hill Companies, srl 29 Strutture di controllo in C Informatica A – V. Perrone Il C consente di eseguire operazioni di somma e sottrazione su puntatori. Se p e a forniscono lindirizzo di memoria di elementi di tipo opportuno, p+i e a+i forniscono lindirizzo di memoria delli-esimo elemento successivo di quel tipo Se i è una variabile intera: la notazione a[i] è equivalente a *(a+i) Analogamente, se p è dichiarato come puntatore a una variabile di tipo int : la notazione p[i] è equivalente a *(p+i). Ne segue che: p = a è equivalente a p = &a[0]; p = a+1 è equivalente a p = &a[1]; Mentre non sono ammessi assegnamenti ad a del tipo: a = p; a = a +1; Array e puntatori (2)
Copyright © The McGraw-Hill Companies, srl 30 Strutture di controllo in C Informatica A – V. Perrone Se p e q puntano a due diversi elementi di un array, p–q restituisce un valore intero pari al numero di elementi esistenti tra lelemento cui punta p e lelemento cui punta q. Non la differenza tra il valore dei puntatori. Supponendo che il risultato di p–q sia pari a 3 e supponendo che ogni elemento dellarray sia memorizzato in 4 byte, la differenza tra lindirizzo contenuto in p e lindirizzo contenuto in q darebbe 12. Array e puntatori (3)
Copyright © The McGraw-Hill Companies, srl 31 Strutture di controllo in C Informatica A – V. Perrone I tipi strutturati: 2. Il costruttore struct Tipo impiegato: nome, cognome, codice fiscale, indirizzo, numero di telefono, eventuali stipendio, data di assunzione e via di seguito. Tipo famiglia: un certo insieme di persone, un patrimonio, costituito a sua volta da un insieme di beni, ognuno con un suo valore, un reddito annuo, spese varie, … Queste strutture informative sono eterogenee: larray non si presta a questo tipo di aggregazione. Il costruttore di record (parola chiave struct in C) è la risposta a questo tipo di esigenze.
Copyright © The McGraw-Hill Companies, srl 32 Strutture di controllo in C Informatica A – V. Perrone typedef char String[50 ]; typedef struct{intGiorno; intMese; intAnno; } Data; typedef struct{StringDestinatario; intImporto; DataDataEmissione; } DescrizioneFatture; Esempi (1)
Copyright © The McGraw-Hill Companies, srl 33 Strutture di controllo in C Informatica A – V. Perrone typedef enum {On, Off} AccType; typedef struct{intCanale; AccTypeAccensione; doubleCursoreLuminosita, CursoreColore, CursoreVolume; } CanaliTV; Esempi (2)
Copyright © The McGraw-Hill Companies, srl 34 Strutture di controllo in C Informatica A – V. Perrone typedef enum {Dirigente, Impiegato, Operaio} CatType; typedef struct{StringNome; StringCognome; intStipendio; charCodiceFiscale[16]; DataDataAssunzione; CatTypeCategoria; } Dipendenti; Esempi (3)
Copyright © The McGraw-Hill Companies, srl 35 Strutture di controllo in C Informatica A – V. Perrone Dichiarazione di variabili La dichiarazione di variabili procede poi come al solito: DipendentiDip1, Dip2; Oppure è possibile definire il nuovo tipo in forma anonima e nello stesso tempo dichiarare le variabili: struct{ StringNome; StringCognome; int Stipendio; char CodiceFiscale[16]; DataDataAssunzione; CatTypeCategoria; } Dip1, Dip2;
Copyright © The McGraw-Hill Companies, srl 36 Strutture di controllo in C Informatica A – V. Perrone Per accedere alle singole componenti del record, si usa una notazione detta dot notation: Dip1.Stipendio = Dip1.Stipendio + (Dip1.Stipendio*10) / 100; Dip1.DataAssunzione.Giorno = 3; Dip1.DataAssunzione.Mese = 1; Dip1.DataAssunzione.Anno = 1993; if (Dip1.Cognome[0] == 'A') … DichiarazioneFattureArchivioFatture[1000]; if(ArchivioFatture[500].DataEmissione.Anno <= 2000) printf("%d", ArchivioFatture[500].Importo); else printf("La fattura in questione è stata emessa dopo il 2000\n"); Accesso alle componenti del record
Copyright © The McGraw-Hill Companies, srl 37 Strutture di controllo in C Informatica A – V. Perrone Una tipica abbreviazione del C... Definiamo un record e dichiariamo una variabile puntatore: typedef struct{intPrimoCampo; charSecondoCampo; } TipoDato; TipoDato x, *P; P = &x; Accesso al campo PrimoCampo di x, attraverso il puntatore P, usando la dot notation: (*P).PrimoCampo = 12; /* Inserisce 12 nel campo PrimoCampo di x */ Esiste una sistassi abbreviata: P–>PrimoCampo = 12; /* Inserisce 12 nel campo PrimoCampo di x */
Copyright © The McGraw-Hill Companies, srl 38 Strutture di controllo in C Informatica A – V. Perrone Assegnamento tra record Una stranezza del C: come abbiamo visto, non è permesso scrivere un assegnamento tra array Array2 = Array1; Invece: Dip1 = Dip2; E lecito e fa esattamente ciò che ci si aspetta: copia lintera struttura Dip1 in Dip2, comprese le sue componenti che sono costituite da array! Il perché di questa stranezza risiede nel modo in cui in C sono realizzati gli array e potrà essere capito tra breve
Copyright © The McGraw-Hill Companies, srl 39 Strutture di controllo in C Informatica A – V. Perrone /* Programma Dirigenti */ #include main() { typedef enum{dirigente, impiegato, operaio CatLav; typedef struct{charNome[30]; charCognome[30]; CatLavCategoria; intStipendio; charCodiceFiscale[16]; } Lavoratore; LavoratoreDatiLavoratori[300]; Lavoratore*Management[10];... Programma Dirigenti (1)
Copyright © The McGraw-Hill Companies, srl 40 Strutture di controllo in C Informatica A – V. Perrone /* Programma Dirigenti (continuazione) */... i = 0; while (i < 10) { if (Management[i]–>Stipendio > ) { j = 0; while (j < 30) { printf("%c", Management[i]–>Cognome[j]); j = j + 1; } printf("%d \n", Management[i]–>Stipendio); } i = i + 1; } Programma Dirigenti (2)
Copyright © The McGraw-Hill Companies, srl 41 Strutture di controllo in C Informatica A – V. Perrone Attenzione ai rischi dei puntatori Effetti collaterali (side effects): *P = 3; *Q = 5; P = Q; /* a questo punto *P = 5 */ *Q = 7; A questo punto *Q = 7, ma anche *P = 7 Un assegnamento esplicito alla variabile puntata da Q determina un assegnamento nascosto alla variabile puntata da P. Caso particolare di aliasing, ovvero del fatto che uno stesso oggetto viene identificato in due modi diversi.
Copyright © The McGraw-Hill Companies, srl 42 Strutture di controllo in C Informatica A – V. Perrone Operazioni applicabili a variabili puntatori: assegnamento dellindirizzo di una variabile tramite loperatore unario & ; assegnamento del valore di un altro puntatore; assegnamento del valore speciale NULL. Se una variabile puntatore ha valore NULL, *P è indefinito: P non punta ad alcuna informazione significativa. loperazione di dereferenziazione, indicata dalloperatore * ; il confronto basato sulle relazioni ==, !=, >, = ; operazioni aritmetiche lassegnamento di indirizzi di memoria a seguito di operazioni di allocazione esplicita di memoria (gli ultimi due casi verranno trattati in seguito); Riassumendo e completando