Oppure

Loading
21/01/16 16:08
TheDarkJuster
Provo a spiegare io il concetto di puntatore in parole molto, molto, molto semplici.
hai un foglietto di carta. Si chiama bob. Su bob puoi scrivere ogni numero che è contenuto in 4 byte.

In pratica hai:
 int bob;


Fino a qui nulla di male. I 4 bytes SONO bob. I 4 bytes sono allocati nello stack.
Ora.... hai un foglietto di carta uguale a bob, ma invece di scrivere i numeri su quel foglietto..... lo usi per ricordarti DOVE si trova bob!

 int *dove_si_trova_bob = &bob;


L'operatore & in questo caso è usato per ottenere l'indirizzo in memoria di bob.

Da notare che bob e dove_si_trova_bob sono due cose completamente diverse!
dove_si_trova_bob sarà qualcosa tipo "a casa sua", mentre bob sarà per esempio 0xFF5603AB (un numero a caso che ci sta in 4 bytes).

bob e dove_si_trova_bob SONO due aree di memoria DIVERSE.

tu puoi modificare direttamente bob:
bob = 0xFFFF03AC;


oppure puoi usare il suo indirizzo per trovare bob e poi modificarlo:
*(dove_si_trova_bob) = 0xFFFF03AC;


Perchè quel *() ? Beh perchè dove_si_trova_bob è una serie di bytes. Se tu facessi:

dove_si_trova_bob = 0xFFFF03AC;


avresti un promemoria a dove si trova billy (0xFFFF03AC), e avresti perso l'indirizzo di bob!

Da questo ragionamento puoi dedurre diverse cose:
dove_si_trova_bob è un puntatore e come tale è un numero che il sistema operativo usa per trovare bob.
Se modifichi (per errore) dove_si_trova_bob al posto di *(dove_si_trova_bob) non riuscirai più a trovare bob, se bob era memoria allocata sull'heap tramite malloc() di cui non hai altri riferimenti.

Vediamo:
 int *dove_si_trova_bob = malloc(sizeof(int));

 //bob non è più spazio allocato nello stack. Ora è spazio allocato nell' heap. Però è pur sempre un foglietto di carta in cui ci stanno 4 byte!!!!

 //prima, quando era allocato nello stack, bob veniva "deallocato" automaticamente. Ora invece dobbiamo deallocarlo "a mano"
 free(dove_si_trova_bob);

 //Però....... ora dove_si_trova_bob ha ancora il vecchio indirizzo di bob! Nonostante bob non sia più lì! Ora ci abita tizio, e non mi sembra giusto andare (accidentalmente) a disturbare tizio:
 dove_si_trova_bob = (int*)NULL;


"Piccola curiosità" (importantissima). La dimensione di ogni puntatore è fissa, e dipende da come è fatta la CPU che eseguirà il programma. Non c'è differenza tra char*, void*, int*, struct dati* e ogni qualsiasi altro puntatore.
prova tu stesso:
if (sizeof(char*) == sizeof(int*)) {
    printf("I puntatori hanno ugual dimensione");
}

Questo perchè? Beh perchè la differenza di dimensione sta nella memoria allocata per mantenere i dati, non in quella che mantiene il riferimento ai dati!

Ma allora..... Perchè il tipo puntatore non è unico, ed esistono char*, void*, struct data*, int*, short* ecc....???
Perchè così il compilatore sa cosa vuoi fare della memoria puntata!!!
void* dove_si_trova_bob = &bob;
int sosia_di_bob = *(dove_si_trova_bob);


C'è un problema....... Il compilatore non sa quanti dati copiare da bob a sosia_di_bob! un byte? due? quattro? otto? 3GB?
In realtà c'è di più da dire, ma mi sembra che questa sia una spiegazione abbastanza semplice da poter essere compresa senza troppo sforzo.

Scusa se ti ho annoiato. Ora, nelle mie intenzioni, dovresti riuscire a capire ciò che scrive il tuo libro.
aaa
21/01/16 17:02
Grazie della spiegazione TheDarkJuster
21/01/16 19:46
A parte la teoria di base sui puntatori, la questione che stai affrontando è la posizione in cui allocare i buffer di memoria che ti servono.

Puoi

1) allocare il buffer prima di chiamare la funzione e liberarla dopo la sua chiamata quando non se ne ha più bisogno (la responsabilità di allocare/liberare la memoria è del "chiamante";)

2) effettuare l'allocazione all'interno della funzione e liberarla dopo la sua chiamata quando non se ne ha più bisogno (la responsabilità di allocare è della funzione e di liberare la memoria del chiamante)

Tutti e due i metodi sono accettabili, basta che la cosa sia documentata. Ad esempio, Windows presenta delle API che si comportano in un modo e API che si comportano nell'altro.
21/01/16 19:46
TheDarkJuster
Oh, di niente.

Se hai bisogno di altro chiedi pure.
aaa
22/01/16 9:10
Grazie ad entrambi,
penso che sceglierò la 1° soluzione nessuno, avere allocazione/deallocazione nella stessa funzione mi sembra più "ordinato".
a proposito di API, se posso chiederlo qui, ok, altrimenti faccio un'altro tread, no problem:

Qualche buona guida?(conosco le MSDN e le consulto, ma in giro c'è altro fatto più alla mano?)
oppure visto che sono prerogativa di windows, sarebbe opportuno andare su funzioni e librerie dello standard?

Stessa cosa per le system() , molti le sconsigliano a favore delle API. avete delucidazioni in merito?
22/01/16 9:31
Postato originariamente da Mikelius:

Grazie ad entrambi,
penso che sceglierò la 1° soluzione nessuno, avere allocazione/deallocazione nella stessa funzione mi sembra più "ordinato"


Forse non è stato chiaro ma la prima soluzione non prevede allocazione/deallocazione nella stessa funzione. Se la funzione deve restituire un buffer non avrebbe senso liberarlo nella stessa funzione! E' il chiamante che la dealloca.

Per le API, ti consiglio di consultare sempre e solo MSDN.

Le funzioni standard e le API sono cose diverse. Una non esclude l'altra.

La system implica l'esecuzione del command processor del sistema operativo e non lo ritengo né utile né necessario.
Evitala e fai quello che ti serve con le funzioni e codice C puro.
22/01/16 10:17
Postato originariamente da nessuno:

1) allocare il buffer prima di chiamare la funzione e liberarla dopo la sua chiamata quando non se ne ha più bisogno (la responsabilità di allocare/liberare la memoria è del "chiamante";)



La si alloca nel main() e la si libera a fine main(), ed il main() è anch'essa una funzione, o sbaglio?



Per le API, ti consiglio di consultare sempre e solo MSDN.

Le funzioni standard e le API sono cose diverse. Una non esclude l'altra.

La system implica l'esecuzione del command processor del sistema operativo e non lo ritengo né utile né necessario.
Evitala e fai quello che ti serve con le funzioni e codice C puro.
22/01/16 10:19
Postato originariamente da Mikelius:
La si alloca nel main() e la si libera a fine main(), ed il main() è anch'essa una funzione, o sbaglio?


Non è affatto detto. La puoi allocare in una funzione chiamata e liberare in una funzione chiamante, qualsiasi siano le funzioni.