• Non ci sono risultati.

Allocazione dinamica della memoria

N/A
N/A
Protected

Academic year: 2022

Condividi "Allocazione dinamica della memoria"

Copied!
28
0
0

Testo completo

(1)

Allocazione dinamica della memoria

• La creazione di nuove variabili a run time (tipo new in Java) viene effettuata in C

utilizzando le funzioni di libreria standard che permettono l’allocazione dinamica di porzioni contigue di memoria

– malloc, calloc, realloc – #include <stdlib.h>

Con queste primitive è possibile creare

dinamicamente variabili e array di dimensione

(2)

Array dinamici -- malloc( )

• Vediamo come creare dinamicamente un array di 10 posizioni

int * a; /*conterrà il puntatore al primo elemento dell’array*/

a = malloc(10*sizeof(int));

heap 40 byte

Punta allʼindirizzo iniziale della nuova

area allocata 100

96

(3)

Array dinamici -- malloc( ) (2)

• Vediamo come creare dinamicamente un array di 10 posizioni

int * a; /*conterrà il puntatore al primo elemento dell’array*/

a = malloc(10*sizeof(int));

if (a == NULL) printf(“fallimento!\n”);

Se malloc non riesce ad allocare

lʼarea di memoria richiesta restituisce NULL (verificare…)

(4)

Array dinamici -- malloc( ) (3)

• Vediamo come creare dinamicamente un array di 10 posizioni

int * a; /*conterrà il puntatore al primo elemento dell’array*/

a = malloc(10*sizeof(int));

if (a == NULL) printf(“fallimento!\n”);

else {

a[4] = 345;

… }

Lʼarray si può accedere con i consueti heap

40 byte

100 96

(5)

Array dinamici -- malloc( ) (4)

• malloc non inizializza la memoria a 0!

– Possiamo inizializzarla esplicitamente o – usare calloc

int * a; /*conterrà il puntatore al primo elemento dell’array*/

a = calloc(10*sizeof(int));

If (a == NULL) printf(“fallimento!\n”);

else {

a[4] = 345;

(6)

Array dinamici -- realloc( )

• realloc modifica la lunghezza di un’area allocata precedentemente

int * a, * b; /*puntatori al primo elemento dell’array*/

a = malloc(10*sizeof(int));

b = realloc(a,20*sizeof(int));

/* adesso b punta ad un array di 20 elementi */

(7)

Array dinamici -- realloc( ) (2)

• Meglio usare sempre due puntatori diversi (a,b) !

– Altrimenti in caso di fallimento NULL sovrascrive il

vecchio puntatore

(8)

Array dinamici -- free( )

• Lo spazio allocato sullo heap non viene deallocato all’uscita delle funzioni

• La deallocazione deve essere richiesta esplicitamente usando free

int * a;

a = malloc(10*sizeof(int));

free(a);

/* se qua accedo di nuovo ad a può succedere di tutto */

(9)

tipo puntatore generico: void *

• non si può dereferenziare

• è necessario un cast prima di manipolare la variabile puntata

– Es.

void * c;

int a;

c = &a;

*c = 5; /* scorretto*/

*(int *)c = 5; /* corretto*/

(10)

tipo puntatore generico: void * (2)

• Serve a scrivere funzioni ‘polimorfe’ in una maniera un po’ brutale

• Esempio

– il tipo della malloc è

void * malloc (unsigned int size);

– quando scrivo

int * a;

a = malloc(10*sizeof(int));

viene effettuato un cast implicito a (int *)

(11)

tipo puntatore generico: void * (3)

• Tipi delle altre funzioni di allocazione e deallocazione

void * calloc (unsigned int size);

void * realloc (void * ptr,

unsigned int size);

void free (void * ptr);

(12)

I puntatori a funzione

• Consideriamo la funzione

int somma (int x, int y) { return x + y;

}

– se proviamo ad eseguire

printf(“%p”, somma);

otteniamo un valore esadecimale che

rappresenta un indirizzo legale del nostro programma

– ??????????????????????????

(13)

I puntatori a funzione (2)

• Consideriamo la funzione

int somma (int x, int y) { return x + y;

}

Codice compilato

di somma IND

somma è un puntatore costante

(14)

I puntatori a funzione (3)

• Consideriamo la funzione

int somma (int x, int y) { return x + y;

}

/* variabile di tipo funzione (int,int)->int */

int (*fun) (int,int);

int a;

fun = somma;

a = fun(3,5);

(15)

I puntatori a funzione (4)

• Consideriamo la funzione

int somma (int x, int y) { return x + y;

}

/* variabile di tipo funzione (int,int)->int */

int (*fun) (int,int);

int a;

fun = somma;

Ma a che serve

????????????

(16)

I puntatori a funzione (5)

• Serve a definire funzioni che prendono come argomenti altre funzioni (di ordine superiore)

void map (int (*fun) (int), int x[ ], int l) { for(i = 0; i < l; i++) x[i] = fun(x[i]);

}

è un iteratore che applica la funzione fun a

tutti gli elementi dell’array x

(17)

I puntatori a funzione (6)

• Esempio di uso della map

int piu_uno (int x) { return x+1;}

int quad (int x) { return x*x;}

int a[3] = {3,4,5};

map(piu_uno,a,3); /* somma uno a tutti gli elementi */

map(quad,a,2); /* eleva al quadrato i primi due elementi */

(18)

Argomenti della linea di comando

• Gli argomenti della linea di comando sono accessibili all’interno della funzione main

– il SO li inserisce sullo stack prima di attivare il processo

– il formato in cui sono resi disponibili è fisso

int main (int argc, char * argv[ ]) {

}

Numero di argomenti nella linea di comando

Array di puntatori agli argomenti

(ciascuno è una stringa, tipo char*)

(19)

Argomenti della linea di comando (2)

• Esempio

%> a.out una stringa per a.out

5 argc

argv p e r \O

a . o u t \O

s t r i n g u n a \O

a \O argv[0]

(20)

Argomenti della linea di comando (3)

• Esempio : Schema di programma che stampa gli argomenti sulla linea di comando

int main (int argc, char * argv[ ]) {

for(i = 0; i < argc; i++)

printf(“arg %d: %s”, i, argv[i]);

}

(21)

Array multidimensionali come array di puntatori

• Vogliamo permettere la definizione di

funzioni su array multidimensionali che non dipendono dal valore delle dimensioni

successive alla prima

int sum_mat (int ** MAT,

int n, int m) {

}

Nome della matrice

Numero di righe, colonne

(22)

Array multidimensionali come array di puntatori (2)

• Vogliamo accedere agli elementi dell’array usando la solita notazione [-][-]

int sum_mat (int ** MAT,

int n, int m) {

MAT[i][j] = …;

}

*(MAT + i*m + j) Il compilatore

dovrebbe conoscere il legame fra questi due oggetti

(23)

Array multidimensionali come array di puntatori (3)

• Una alternativa: abbandonare l’allocazione contigua per righe

MAT

7 2 6 2 1 2 3 4

4 6 1 2 MAT[0]

MAT[1]

3 5 7 9 MAT[2]

MAT[3]

MAT[4]

MAT[2][2]

(24)

Array multidimensionali come array di puntatori (4)

• Una alternativa: vediamo i tipi ...

MAT

7 2 6 2 1 2 3 4

4 6 1 2

4 5 1 2 MAT[0]

MAT[1]

3 5 7 9 MAT[2]

MAT[3]

MAT[4]

MAT[2][2]

int**

int*[5]

int[4]

(25)

Array multidimensionali come array di puntatori (5)

• Una alternativa: in memoria non ho più aree contigue ...

MAT 1 2 3 4

4 6 1 2 MAT[0]

3 5 7 9

40 44 48 52

40 120140400 4

70 74 78 82 86

120 124 128 132 140 144 148 152 indirizzo

valore

(26)

Array multidimensionali come array di puntatori (6)

• Perché funziona?

int sum_mat (int ** MAT,

int n, int m) {

MAT[i][j] = …;

}

*(*(MAT + i) + j) Questo legame non interessa più!

(27)

Array multidimensionali come array di puntatori (7)

• Funzione di allocazione

int ** mat_new(unsigned int m, unsigned int n) {

int i, ** a, errore = FALSE;

a = malloc(m*sizeof(int*));

if (a == NULL) return NULL;

for(i = 0; (i < m) && (!errore); i++) { a[i] = malloc(n*sizeof(int));

if (a[i] == NULL) errore = TRUE;

}

if (errore) /* gestione errori */

(28)

Array multidimensionali come array di puntatori (8)

• Funzione di deallocazione

void mat_free(int ** a, unsigned int m)

{

int i;

/* dealloco tutte le righe */

for(i = 0; i < m; i++) free(a[i]);

/* dealloco l’array dei puntatori alle righe */

free(a);

Riferimenti

Documenti correlati

[r]

• se il secondo argomento sulla linea di comando ` e -p (province), allora ci dovr`a essere un terzo argomento corrispondente al nome di una regione: in questo caso dovranno

Un file di testo contiene i dati sulle precipitazioni (in millimetri) relativi a ciascun mese di svariati anni..

di un tipo all’interno della sua dichiarazione... Se risulta minore o uguale lo si pone nel sottoalbero di risulta minore o uguale, lo si pone nel sottoalbero di sinistra, ovvero

 Python mette a disposizione il modulo optparse per la definizione ed il parsing delle opzioni da riga di comando5. from optparse

• Gli argomenti della linea di comando sono accessibili all’interno della funzione main. – il SO li inserisce sullo stack prima di attivare

L’allocazione dinamica della memoria si verifica quando un programma richiede al sistema operativo un blocco di memoria dichiarando, preventivamente, la dimensione dello stesso..

Ridimensiona un blocco Heap già allocato, portandolo a NewSize byte; restituisce un puntatore void al blocco di memoria riallocato ed eventualmente spostato. Il contenuto del