Skip to content

Instantly share code, notes, and snippets.

@bebosudo
Last active October 9, 2017 21:46
Show Gist options
  • Save bebosudo/a662d842ab74c390d6c9fbfa642ab92a to your computer and use it in GitHub Desktop.
Save bebosudo/a662d842ab74c390d6c9fbfa642ab92a to your computer and use it in GitHub Desktop.
Allocations example and differences between static and dynamic allocation (in stack and heap). Italian.
/*
Da compilare su linux con:
gcc -o allocation_examples allocation_examples.c
oppure se si vuole usare il vecchio standard del C dell'89:
gcc --std=c89 -o allocation_examples allocation_examples.c
Si puo' poi eseguire facendo:
./allocation_examples
*/
#include <stdio.h>
#include <stdlib.h>
int incrementa(int variabile_da_incrementare);
int incrementa2(int variabile_da_incrementare);
int incrementa3(int * variabile_da_incrementare);
int main() {
/* Variabile definita all'interno dello stack.*/
int numero = 5;
/*scanf("" .... ); // questo sai farlo anche te */
printf("var nello stack=%d\n", numero);
printf("indirizzo nello stack=%p\n\n", &numero);
/* Variabile definita nell'heap. |_0xasdf_| --> (heap) |14| */
int* numero_nell_heap;
numero_nell_heap = malloc(sizeof(int) * 1);
*numero_nell_heap = 14;
/* numero_nell_heap (scritto cosi' com'e') e' un numero che dice al
// programma dove andare a trovare il contenuto della cella puntata
// dal puntatore (all'interno dell'heap, che e' la memoria che contiene
// le allocazioni dinamiche.. e' come una nuvola dove puoi buttare
// dentro variabili dinamicamente).
*/
printf("indirizzo di cio' a cui punta numero_nell_heap (=della cella puntata)= %p\n", numero_nell_heap);
/* In questo modo andiamo a vedere (nello stack!) dove si trova la
// cella che contiene il puntatore al nostro valore 14.
*/
printf("indirizzo NELLO STACK di numero_nell_heap= %p\n", &numero_nell_heap);
/* Per vedere il valore contenuto dalla variabile numero_nell_heap
// quando si usa il * si chiama de-referenziazione.
*/
printf("%d\n", *numero_nell_heap);
/* breve esempio sul perche' sono utili i puntatori (non centra l'alloc
// dinamica ancora).
*/
printf("\n\n-----------------------------------------------\nPrimo incremento (non funzia)\n", numero); /* numero=5 */
printf("fuori prima di chiamare incr numero e' =%d\n", numero); /* numero=5*/
incrementa(numero);
printf("fuori dopo incr1 numero e'=%d\n\n", numero); /* numero=?
// numero "vorremmo" che diventasse 6, ma in realta la variabile `numero`
// viene copiata dentro alla funzione `incrementa`, quindi il suo
// cambiamento sara' solo locale (!) dentro alla funzione! cioe' sono
// due variabili diverse salvate in posti diversi.
*/
printf("\nsecondo metodo di incremento (non funzia)\n");
printf("l'indirizzo di `numero` fuori prima di incr2 e'=%p e val=%d\n", &numero, numero);
incrementa2(numero);
printf("l'indirizzo di `numero` fuori dopo incr2 e' = %p e val=%d\n", &numero, numero);
printf("\nterzo metodo di incremento (funzia!)\n");
/* Usiamo un incrementa che funziona finalmente! */
printf("l'indirizzo di `numero` fuori prima di incr2 e'=%p e val=%d\n", &numero, numero);
incrementa3(&numero); /* passaggio per riferimento (tecnicamente, viene
// fatta una copia del puntatore nella variabile
// interna alla funzione.. e' un po' come se copiassi
// l'indirizzo di casa da dare ai tuoi amici su un
// pezzo di carta).
*/
printf("l'indirizzo di `numero` fuori dopo incr2 e' = %p e val=%d\n", &numero, numero);
/* L'allocazione dinamica ha senso quando devi allocare dati di cui non
// sai la lunghezza (la variabile intera di prima non ha molto senso
// allocarla nell'heap in realta')
*/
printf("\n\n-------------------\nESEMPIO array dinamico\n", *numero_nell_heap);
int lunghezza_array;
printf("quanto lungo? ");
/* Anche con la scanf dobbiamo usare il riferimento della variabile
// in cui vogliamo salvare il dato, altrimenti "lunghezza_array" viene
// copiato (!) dentro alla funzione scanf, viene sovrascritto localmente
// (dentro alla funzione), ma fuori nel main rimane uguale.
// Es: funzione incrementa qua sotto.
*/
scanf("%d", &lunghezza_array);
printf("creo un array lungo %d\n", lunghezza_array);
/* Siccome la lunghezza di questo array puo' essere decisa dall'utente
// "al momento dell'esecuzione" (in inglese: "at run-time"), il
// compilatore non puo' sapere quanto spazio preparare per questo array.
// Quindi qualcosa come questo non funziona (o forse funziona, ma causa
problemi, ad es perche' lo stack, che e' la porzione di memoria dove le
variabili definite "normalmente" vengono salvate, ha una dimensione fissa
in genere ad 8MB su linux: superata quella cifra, ci sono rogne).
La dimensione dello stack si puo' trovare scrivendo
ulimit -s
nella console (bash) di linux: ritorna un numero che sono i KB dello stack.
*/
/* int array_statico[lunghezza_array]; */
int* array_dinamico;
array_dinamico = malloc(sizeof(int) * lunghezza_array);
/* bisogna sempre controllare che la malloc abbia ritornato effettivamente
un puntatore ad un pezzo di memoria valido (perche' se non c'e' + spazio
nell'heap, malloc ritorna un puntatore che punta a NULL, che e' un valore
speciale)
*/
if (array_dinamico==NULL) {
/* vuol dire che non c'e' piu' spazio per creare l'array con il numero
di int richiesti */
printf("finita la memoria!\n");
return;
}
int i=0;
for (; i<lunghezza_array; i++) {
array_dinamico[i] = i + 2; /* il + 2 e' solo per cambiare un po' i dati */
}
/* giusto per fare qualcosa con l'array, adesso lo stampiamo */
for (i=0; i<lunghezza_array; i++) {
printf("(indice=%d, valore=%d)\n", i, array_dinamico[i]);
}
printf("\n");
/* va sempre deallocata a mano la memoria che viene richiesta a mano con
malloc */
free(numero_nell_heap);
free(array_dinamico);
return;
}
int incrementa(int variabile_da_incrementare) {variabile_da_incrementare++;}
int incrementa2(int variabile_da_incrementare) {
printf("prima var aveva valore=%d e indirizzo in mem=%p\n", variabile_da_incrementare, &variabile_da_incrementare);
variabile_da_incrementare++;
printf("dopo var ha valore=%d e indirizzo in mem=%p\n", variabile_da_incrementare, &variabile_da_incrementare);
}
int incrementa3(int *variabile_da_incrementare) {
printf("prima var aveva valore=%d e indirizzo in mem=%p\n",
*variabile_da_incrementare, variabile_da_incrementare);
(*variabile_da_incrementare)++;
printf("dopo var ha valore=%d e indirizzo in mem=%p\n",
*variabile_da_incrementare, variabile_da_incrementare);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment