PDA

View Full Version : [C#]primi dubbi


RaouL_BennetH
21-08-2005, 15:27
Seguendo i vostri consigli,ho cominciato a studiare un pò il C# da alcune guide ed ora mi si pone il primo problema dovuto all'ignoranza di certe cose ovvero:

Studiando i tipi struct e le classi,ho ben capito alcune delle differenze che esistono fra di loro ovvero:

1) Un tipo struct non supporta l'ereditarietà mentre un tipo class si.
2) Un tipo struct è un tipo valore e non un tipo riferimento.

E il punto due mi manda in tilt.
Documentandomi,credo di aver capito che i tipi valore vengono memorizzati in un'area di memoria chiamata stack,che a sua volta è una struttura che utilizza il concetto di "pila" per memorizzare i dati con il metodo LIFO,che,sempre se non ho capito male,significa che l'ultimo dato memorizzato sarà sempre il primo ad essere estratto.
Invece un tipo "riferimento" come una classe,utilizza un'area di memoria detta heap.
Adesso,se volessi capire in termini fisici queste due diverse aree di memoria(stack e heap),mi consigliate di studiarmele:

- ognuna per conto proprio
- avere un concetto generale
- che importanza ha conoscerle bene

insomma,qualsiasi cosa che possa chiarirmi questi primi dubbi :)

Thx.

RaouL.

VICIUS
22-08-2005, 01:26
Seguendo i vostri consigli,ho cominciato a studiare un pò il C#
Bravo!

Studiando i tipi struct e le classi,ho ben capito alcune delle differenze che esistono fra di loro ovvero:

1) Un tipo struct non supporta l'ereditarietà mentre un tipo class si.
2) Un tipo struct è un tipo valore e non un tipo riferimento.
l'ereditarietà non è che la punta dell'iceberg. Ma va bene cosi. Piano piano scoprirai anche quello che c'è sotto. ;)

E il punto due mi manda in tilt.
Documentandomi,credo di aver capito che i tipi valore vengono memorizzati in un'area di memoria chiamata stack,che a sua volta è una struttura che utilizza il concetto di "pila" per memorizzare i dati con il metodo LIFO,che,sempre se non ho capito male,significa che l'ultimo dato memorizzato sarà sempre il primo ad essere estratto.
Invece un tipo "riferimento" come una classe,utilizza un'area di memoria detta heap.
Adesso,se volessi capire in termini fisici queste due diverse aree di memoria(stack e heap),mi consigliate di studiarmele:

- ognuna per conto proprio
- avere un concetto generale
- che importanza ha conoscerle bene

insomma,qualsiasi cosa che possa chiarirmi questi primi dubbi :)

Thx.

RaouL.
Dunque forse la confuzione è dovuta ad una traduzione venuta male. Nelle guide che stai leggendo.
Le struct sono tipi di dato passati per valore. Come gli int, byte, double...
Quando chiami una funzione il dato contenuto viene preso e copiato in una nuova variabile all'interno dello stack. Quindi anche se la funzione chiamata modifica il valore, la variabile originale all'interno della chiamante non ne risente.

Le classi invece vengono create dinamicamente nel heap. Quando chiami una funzione e gli passi il nome di un oggetto che hai appena creato non fai altro che passargli un riferimento alla memoria in cui è stato creato. In questo caso se la funzione chiamata modifica qualcosa la modifica si propaga anche alla chiamante.

ciao ;)

RaouL_BennetH
22-08-2005, 01:28
Bravo!


l'ereditarietà non è che la punta dell'iceberg. Ma va bene cosi. Piano piano scoprirai anche quello che c'è sotto. ;)


Dunque forse la confuzione è dovuta ad una traduzione venuta male. Nelle guide che stai leggendo.
Le struct sono tipi di dato passati per valore. Come gli int, byte, double...
Quando chiami una funzione il dato contenuto viene preso e copiato in una nuova variabile all'interno dello stack. Quindi anche se la funzione chiamata modifica il valore, la variabile originale all'interno della chiamante non ne risente.

Le classi invece vengono create dinamicamente nel heap. Quando chiami una funzione e gli passi il nome di un oggetto che hai appena creato non fai altro che passargli un riferimento alla memoria in cui è stato creato. In questo caso se la funzione chiamata modifica qualcosa la modifica si propaga anche alla chiamante.

ciao ;)

questo mi è abbastanza chiaro :(

Ciò che non mi è chairo è cosa sia lo stack e cosa sia l'heap :/

Stasera comunque non può essermi chiaro nulla dato che mi sono scolato una marea di alcool!!! :D :ubriachi:

VICIUS
22-08-2005, 01:43
questo mi è abbastanza chiaro :(

Ciò che non mi è chairo è cosa sia lo stack e cosa sia l'heap :/

Stasera comunque non può essermi chiaro nulla dato che mi sono scolato una marea di alcool!!! :D :ubriachi:
Dunque per dirla in poche parole sono entrambe due zone di memoria.
Lo stack viene usato per parcheggiare temporaneamente i parametri da passare alle funzioni e altre informazioni. In genere sugli x86 e limitato a 64k ma può variare tranquillamente. Il mio professore mi diceva sempre di pensare ad una pila di tazzine di caffè appese al soffitto. Io non ho mai capito che cosa intendesse con quel esempio, vedi te se capisci che cosa voleva dire :D

L'heap è simile. Qui viene allocata la memoria dal sistema operativo quando il tuo programma richiede un po' di memoria dinamica. L'heap non è una pila, e tra una zona di memoria e l'altra ci possono essere anche dei buchi.

ciao ;)

ghiotto86
22-08-2005, 08:17
Dunque per dirla in poche parole sono entrambe due zone di memoria.
Lo stack viene usato per parcheggiare temporaneamente i parametri da passare alle funzioni e altre informazioni. In genere sugli x86 e limitato a 64k ma può variare tranquillamente. Il mio professore mi diceva sempre di pensare ad una pila di tazzine di caffè appese al soffitto. Io non ho mai capito che cosa intendesse con quel esempio, vedi te se capisci che cosa voleva dire :D

L'heap è simile. Qui viene allocata la memoria dal sistema operativo quando il tuo programma richiede un po' di memoria dinamica. L'heap non è una pila, e tra una zona di memoria e l'altra ci possono essere anche dei buchi.

ciao ;)

che caxxo di esempio fa il tuo prof :sofico: :sofico:
cmq quoto anche nel fatto che ci sono dei buchi tra queste due aree di memoria,ì; di solito esiste anche un'area dei dati statici e globali.
la politica di gestione dello heap è decisa dall'O.S

Spini
22-08-2005, 20:00
Io sono completamente ignorante di C# e di memoria ne so relativamente poche, comunque, da buon (ex) algoritmista, provo a farti capire cosa siano stack e heap in senso più ampio, slegato dall'implementazione reale.
Uno stack è un metodo di memorizzazione di base, nel senso che non richiede che si conosca alcunché di ciò che c'è stato inserito. Lo puoi immaginare fisicamente come un array, di dimensioni incognite, in cui le uniche operazioni che puoi fare sono aggiungere e rimuovere l'ultimo elemento. Caffè o non caffè, stack significa pila, e questo è esattamente ciò che è: una torre di dati, non puoi toccarla in mezzo ma puoi solo prendere quello che c'è in cima o metterci qualcos'altro.
Detto così sembra solo un modo per limitarsi la libertà piuttosto che usare un array, e in effetti lo è :p tuttavia viene molto usato, da una parte perché a livello teorico fa spesso comodo avere una simile struttura dati, ignorando poi come venga implementata all'atto pratico, dall'altra perché la sua estrema semplicità lo rendono ottimo dove altro non serve. Almeno in linea teorica, aggiungere o rimuovere un oggetto è un'operazione del tutto indipendente dalle dimensioni dello stack, il che è un gran bene.
Il C usa uno stack (invisibile) ad esempio per la ricorsione. Nello stack di memoria si salvano le funzioni aperte. Tutte le macchine reali monoprocessore eseguono una sola operazione alla volta, e di conseguenza processano una sola funzione alla volta. Fondamentalmente, senza scendere in particolari che non conosco, aprendo una funzione i dati ad essa relativi (mi vengono in mente i parametri, forse anche qualcos'altro più low-level) vengono pushati sulla cima dello stack di memoria. Se la funzione chiama un'altra funzione, i suoi dati verranno aggiunti anch'essi allo stack, e quando si chiuderà una funzione sarà di certo l'ultima aggiunta (a meno di violare l'incapsulamento con funzioni tipo exit, ma queste sono eccezioni). Così facendo risulta uno stack, che è la struttura più adatta a mantenere questi dati.

Uno heap è un albero ordinato. Un albero è un grafo senza cicli appeso per una radice. Un grafo è una serie di nodi e rami :)
A livello teorico nello heap i dati sono inseriti nei nodi, collegati tra loro dai rami in modo che non si formino cicli e che ha la struttura tipica di un albero (una radice, da cui si ripartiscono dei rami, da ogni ramo altri rami, finché non si arriva alle "foglie", ovvero nodi senza figli). Spiegarsi senza fare un lungo e noioso preambolo è impossibile, quindi prendi questa definizione per buona :)
L'ordinamento dello heap consiste nell'avere alla radice il valore minimo di tutti, e ad ogni nodo vale la proprietà che non può avere un valore minore del padre (un professore trentino la definiva con un certo humor la "no Edipo property", nessun figlio deve soffrire di minoranza rispetto al padre :D).
Detto così questa cosa apparentemente complicata sembra essere del tutto inutile, in realtà è utilissima in tante situazioni che nemmeno ricordo più da quanto tempo è che non le uso :) Ciò di cui sono sicuro è che se disegni un albero con dentro i tuoi dati l'altezza di questo albero risulterà dell'ordine di grandezza del logaritmo del numero dei dati. Questo significa che se hai 10^10 elementi (un 40 giga di memoria, sai che ram ;) ) la sua altezza sarà di circa 30. Cosa te ne fai di questo? Beh se invece che in uno heap i dati fossero salvati in un array ordinato eliminare o aggiungere un elemento preservando l'ordine ti costerebbe un valore propozionale alla dimensione dell'array (ovvero un tempo decisamente eccessivo), mentre lo heap necessita di un tempo proporzionale all'altezza, ovvero istantaneo nella stragrande maggioranza dei casi.

Ora, da tutto ciò a risalire a struct e classi non so cosa ci corra, se non che sono sicuro esista (come peraltro già detto) una parte della memoria chiamata "stack" che funziona appunto come uno stack, e mi pare di aver capito dalle discussioni precedenti che ne esiste pure una chiamata "heap" che dello heap ha le proprietà...
Ho scritto un pillolone inutile e poco interessante per i più, spero solo che qualcuno sia arrivato fin qui senza imprecare contro di me ;)

RaouL_BennetH
22-08-2005, 22:31
Io sono completamente ignorante di C# e di memoria ne so relativamente poche, comunque, da buon (ex) algoritmista, provo a farti capire cosa siano stack e heap in senso più ampio, slegato dall'implementazione reale.
Uno stack è un metodo di memorizzazione di base, nel senso che non richiede che si conosca alcunché di ciò che c'è stato inserito. Lo puoi immaginare fisicamente come un array, di dimensioni incognite, in cui le uniche operazioni che puoi fare sono aggiungere e rimuovere l'ultimo elemento. Caffè o non caffè, stack significa pila, e questo è esattamente ciò che è: una torre di dati, non puoi toccarla in mezzo ma puoi solo prendere quello che c'è in cima o metterci qualcos'altro.
Detto così sembra solo un modo per limitarsi la libertà piuttosto che usare un array, e in effetti lo è :p tuttavia viene molto usato, da una parte perché a livello teorico fa spesso comodo avere una simile struttura dati, ignorando poi come venga implementata all'atto pratico, dall'altra perché la sua estrema semplicità lo rendono ottimo dove altro non serve. Almeno in linea teorica, aggiungere o rimuovere un oggetto è un'operazione del tutto indipendente dalle dimensioni dello stack, il che è un gran bene.
Il C usa uno stack (invisibile) ad esempio per la ricorsione. Nello stack di memoria si salvano le funzioni aperte. Tutte le macchine reali monoprocessore eseguono una sola operazione alla volta, e di conseguenza processano una sola funzione alla volta. Fondamentalmente, senza scendere in particolari che non conosco, aprendo una funzione i dati ad essa relativi (mi vengono in mente i parametri, forse anche qualcos'altro più low-level) vengono pushati sulla cima dello stack di memoria. Se la funzione chiama un'altra funzione, i suoi dati verranno aggiunti anch'essi allo stack, e quando si chiuderà una funzione sarà di certo l'ultima aggiunta (a meno di violare l'incapsulamento con funzioni tipo exit, ma queste sono eccezioni). Così facendo risulta uno stack, che è la struttura più adatta a mantenere questi dati.

Uno heap è un albero ordinato. Un albero è un grafo senza cicli appeso per una radice. Un grafo è una serie di nodi e rami :)
A livello teorico nello heap i dati sono inseriti nei nodi, collegati tra loro dai rami in modo che non si formino cicli e che ha la struttura tipica di un albero (una radice, da cui si ripartiscono dei rami, da ogni ramo altri rami, finché non si arriva alle "foglie", ovvero nodi senza figli). Spiegarsi senza fare un lungo e noioso preambolo è impossibile, quindi prendi questa definizione per buona :)
L'ordinamento dello heap consiste nell'avere alla radice il valore minimo di tutti, e ad ogni nodo vale la proprietà che non può avere un valore minore del padre (un professore trentino la definiva con un certo humor la "no Edipo property", nessun figlio deve soffrire di minoranza rispetto al padre :D).
Detto così questa cosa apparentemente complicata sembra essere del tutto inutile, in realtà è utilissima in tante situazioni che nemmeno ricordo più da quanto tempo è che non le uso :) Ciò di cui sono sicuro è che se disegni un albero con dentro i tuoi dati l'altezza di questo albero risulterà dell'ordine di grandezza del logaritmo del numero dei dati. Questo significa che se hai 10^10 elementi (un 40 giga di memoria, sai che ram ;) ) la sua altezza sarà di circa 30. Cosa te ne fai di questo? Beh se invece che in uno heap i dati fossero salvati in un array ordinato eliminare o aggiungere un elemento preservando l'ordine ti costerebbe un valore propozionale alla dimensione dell'array (ovvero un tempo decisamente eccessivo), mentre lo heap necessita di un tempo proporzionale all'altezza, ovvero istantaneo nella stragrande maggioranza dei casi.

Ora, da tutto ciò a risalire a struct e classi non so cosa ci corra, se non che sono sicuro esista (come peraltro già detto) una parte della memoria chiamata "stack" che funziona appunto come uno stack, e mi pare di aver capito dalle discussioni precedenti che ne esiste pure una chiamata "heap" che dello heap ha le proprietà...
Ho scritto un pillolone inutile e poco interessante per i più, spero solo che qualcuno sia arrivato fin qui senza imprecare contro di me ;)


Anzi,tutt'altro!! :) Almeno per me è servito a farmi un'idea da approfondire più accuratamente.

Ora,tornando al mio dubbio,credo quindi che grazie alle vostre spiegazioni,mi sia stato fugato.

Thx.
RaouL.

fek
22-08-2005, 22:44
Anzi,tutt'altro!! :) Almeno per me è servito a farmi un'idea da approfondire più accuratamente.

Ora,tornando al mio dubbio,credo quindi che grazie alle vostre spiegazioni,mi sia stato fugato.

Thx.
RaouL.

Pensa ai value type sempre a "come se fossero degli interi".

Questa e' la miglior spiegazione che conosco su che cos'e' esattamente un value type:
http://blogs.msdn.com/slippman/archive/2004/07/23/193353.aspx

mjordan
23-08-2005, 01:02
Il mio professore mi diceva sempre di pensare ad una pila di tazzine di caffè appese al soffitto.

Se mi dici una pila di tazzine ok... L'esempio è calzante... Significa che quando aggiungi tazzine, lo puoi fare solo dall'alto... Cosi' come quando le togli... Lo puoi fare sempre e solo dall'alto.... E questo è l'approccio LIFO...

Ma la cosa che non capisco è perchè devono essere appese al soffitto :D :D :D

VICIUS
23-08-2005, 09:07
Se mi dici una pila di tazzine ok... L'esempio è calzante... Significa che quando aggiungi tazzine, lo puoi fare solo dall'alto... Cosi' come quando le togli... Lo puoi fare sempre e solo dall'alto.... E questo è l'approccio LIFO...

Ma la cosa che non capisco è perchè devono essere appese al soffitto :D :D :D
Guarda il mio professore di sistemi era un gran prof ma ogni tanto gli scappavano ste cose dalla bocca. Ti assicuro che una volta per spiegare la differenza tra little e big endiand si è messo a canticchiare la canzoncina degli indiani.. 1, 2, 3, 4, 5 litle endian... 5, 4, 3, 2, 1 big endian ... :D

Dall'alto perché se non sbaglio in x86 i dati vengono aggiunti dal alto per arrivare fino a 0. Quindi se 0 è il pavimento e 65k è il soffitto.

ciao ;)

cdimauro
23-08-2005, 09:12
Non mi suona molto chiaro: potresti spiegarmi cosa intendi per "aggiungere i dati dall'alto" (per x86)?

VICIUS
23-08-2005, 09:49
Non mi suona molto chiaro: potresti spiegarmi cosa intendi per "aggiungere i dati dall'alto" (per x86)?
Intendo che se lo stack è vuoto l'indice è 65k. Quando aggiungi 1 byte l'indice viene decrementato di 1. Fanno questo cosi possono controllare quando lo stack è pieneo solo con una test e una jump.

ciao ;)

mjordan
24-08-2005, 03:36
Ti assicuro che una volta per spiegare la differenza tra little e big endiand si è messo a canticchiare la canzoncina degli indiani.. 1, 2, 3, 4, 5 litle endian... 5, 4, 3, 2, 1 big endian ... :D


Bhè però è un modo simpatico di far ricordare qualcosa al volo... :)

cdimauro
24-08-2005, 09:08
Intendo che se lo stack è vuoto l'indice è 65k. Quando aggiungi 1 byte l'indice viene decrementato di 1. Fanno questo cosi possono controllare quando lo stack è pieneo solo con una test e una jump.

ciao ;)
Ok, adesso mi è chiaro. Questo comunque vale soltanto per gli 80x86, con x <= 2. Dal 386 in poi e usando la paginazione non è più conveniente farlo.
In realtà non ho mai usato test e jump neppure quando ho scritto codice a 16 bit per x86: troppo oneroso dal punto di vista computazionale.