Newsgroup: it.comp.lang.c++
Titolo: I Puntatori...

Scusate se ogni tanto approfitto della vostra pazienza, ma siete gli unici
che siete in grado di chiarirmi le idee
sui problemi dettati dall'istruzione scolastica che ricevo....
ieri abbiamo introdotto i puntatori,..    "di grande utilità"
.....(dicono).
A me sembrano solamente una copia del valore che assume una variabile,   in
pratica mi sembra più comodo utilizzare la stessa variabile!
Sarà sicuramente una risposta stupida,  ma se avete la bontà di farmi capire
la differenza .....!
:-)
grazie e ciao


Un puntatore e` una sorta di maniglia che permette di aprire le celle che compongono
la ram. In particolare una variabile puntatore contiene indirizzi di memoria.
L'importanza dei puntatori e` dovuta alla loro enorme flessibilita` e potenza che permette
un completo controllo della memoria e ed esempio la realizzazione di strutture dati che
crescono e diminuiscono dinamicamente, permettendo la realizzazione di
programmi che manipolano quantita` di dati note solo a run-time (tipo i text editor...)
Paolo
----------------------------------------------------------
  Paolo Marotta
  Computer Science, University of Pisa
  home:   
http://www.cli.di.unipi.it/~marotta
  e-mail: 
mar...@cli.di.unipi.it
 
----------------------------------------------------------

pratica mi sembra più comodo utilizzare la stessa variabile!
Un puntatore non ottiene una copia della variabile, bensi` mantiene
un *indicatore* alla variabile stessa; indicatore che puo` essere
cambiato (molto rapidamente) nel corso delle operazioni, per passare
ad indicare una variabile diversa, o, anche, "nessuna variabile"
(quest'ultima funzionalita` si ottiene con il "puntatore nullo").
Molti degli usi "classici" dei puntatori (passaggio per riferimento,
invece che per valore, a una funzione; costruzione di strutture
dati) sono molto meno importanti in C++, di quanto lo fossero in
C, in quanto il C++ comprende meccanismi appositi (reference,
per il passaggio di argomenti a funzioni; template e libreria
standard, per la stragrande maggioranza delle strutture dati).
Ma i puntatori restano appropriati [a] per costruire strutture dati
strane/particolari/insolite, [b] tutte le volte che i reference non
sono appropriati perche` serve l'una o l'altra delle due feature
speciali dei puntatori, "passare a indicare una variabile diversa"
e/o "indicare ``nessuna variabile'' [puntatore nullo]".
(Un'altra caratteristica ancora dei puntatori, quella di poterli
assoggettare ad aritmetica d'indirizzi, e` invece veramente
*rarissimo* che serva in C++, essendo un concetto di bassissimo
livello; tuttavia, su questo e` modellato l'intero schema concettuale
degli *iteratori*, che e` di importanza enorme e crescente).
Non e` banale, in C++, dare esempi elementari di uso dei
puntatori che non si risolverebbero meglio con reference,
uso della libreria standard, iteratori, eccetera (in C, dove
tutti questi concetti piu` ad alto livello non esistono e dunque
devi modellarli TUTTI con puntatori, la situazione e` ovviamente
diversa!; ma, se ti interessa discutere di C invece che di C++,
dovresti passare sul gruppo apposito, it.comp.lang.c).
L'esempio elementare piu` importante e` probabilmente il
costrutto "new", che permette di generare un nuovo oggetto
di un certo tipo e *ritorna un puntatore* al nuovo oggetto
(una volta, tornava un puntatore nullo se l'allocazione di
spazio per il nuovo oggetto non era possibile, ma questo
non si applica in C++ standard, dove si usano invece le
eccezioni per segnalare questi casi eccezionali d'errore).
Oggetti costruiti con "new" devono poi a un certo punto
essere distrutti con "delete" applicato allo stesso puntatore
che "new" ha restituito (in molti casi, puoi "rivestire" il
puntatore con un template auto_ptr<> per risparmiarti
quest'ultima necessita`).
Alex


pensa che senza puntatori non si potrbbero fare il 70% delle cose che si
fanno in C o C++ o in qualsiasi altro linguaggio... ma il C in particolare
li predilige...penso che se il C non avesse i puntantori non si potrebbe
neanche chiamare linguaggio di programmazione...
tanto per fare un esempio molto semplice:
metti di dover scrivere una funzione a cui tu passi 2 interi... la funzione
deve darti la somma e il rapporto dei 2 numeri... la somma la passi come
valore di ritorno della funzione.. e il rapporto ?? (o qualsiasi altra cosa
che la funzione vuole restituire? )
senza puntatori c'è un problema...
// -------------------------------------------------------------------------
--------
int operazioni(int a, int b, int rapporto)  {   rapporto=a/b;
                                                                      return
(a+b);     }
// -------------------------------------------------------------------------
--------
main()
  int primo=10;
  int secondo=5;
  int somma=0;
  int rapporto=0;
  somma=operazioni(primo,secondo,rapporto);
  }
dopo la chamata somma avrà 15 ma rapporto sarà sempre 0 perchè il c passa la
variabile rapporto "per valore" cioè ne passa una copia alla funzione ...
che potrà modificare come vuole... ma non è la variabile su cui vuoi
memorizzare il risultato... è solo una var sua interna alla funzione e
all'uscita viene distrutta insieme alla funzione stessa... la tua variabile
rapporto continua ad avere lo stesso valore che aveva prima della
chiamata... non viene mai toccato il suo valore 0...
se invece utilizzi il passaggio per indirizzo (con il puntatore appunto)...
// -------------------------------------------------------------------------
--------
int operazioni(int a, int b, int *rapporto)  {   *rapporto=a/b;
return (a+b);     }
// -------------------------------------------------------------------------
--------
main()
  int primo=5;
  int secondo=6;
  int somma=0;
  int rapporto=0;
  somma=operazioni(primo,secondo, &rapporto);
  }
in questa maniera passi alla funzione l'indirizzo di memoria in cui è
memorizzata la tua variabile rapporto... e la funzione quindi adrà a
scrivere su quella locazione di memoria puntata dal puntantore (&rapporto)
così modifica realmente la variabile.
questo è l'esempio più banale che mi è venuto in mente,,,ma ci sono motivi
ben più importanti per utilizzare i puntatori....
cmq non temere... tra un po' di tempo te ne accorgerai da solo
dell'importanza dei puntatori.... e come se te ne accorgerai..!!!.   :-))
ciao
Salvo

che la funzione vuole restituire? )
In C++, la soluzione piu` naturale e idiomatica sarebbe di passare il
rapporto *per reference*, evitando il puntatore:
    int lafunz(int a, int b, int& rapporto);
e una buona alternativa e` ritornare una struct:
    struct risult { int somma; int rapporto; }
    lafunz(int a, int b);
Quest'ultimo approccio sarebbe possibile anche in C.  Naturalmente,
non va trascurato anche l'idioma che suggerisci tu, soprattutto se
puo` effettivamente interessare usare le proprieta` dei puntatori, come
quella di potere essere NULLI:
    int lafunz(int a, int b, int* pRapporto) {
        if(pRapporto) *pRapporto = a/b;
        return a+b;
    }
Qui, se il chiamante NON e` interessato a un "risultato collaterale"
(il rapporto) potenzialmente costoso da calcolare, lo indica passando
un puntatore nullo; la funzione effettua il calcolo solo se il relativo
risultato interessa al chiamante (testando se il puntatore e` nullo).
Questo idioma non ha un immediato corrispettivo in termini di
reference o ritorno di strutture; notiamo per completezza che
c'e` chi lo detesta come stile, mentre a me sembra naturale,
efficace, e, appunto, "idiomatico" (sfrutta nel modo piu` semplice
e ovvio una cruciale proprieta` dei puntatori che li distingue
dalle reference in termini di passaggio di parametri!).
Alex

 la differenza .....!
L'argomento dei puntatori è piuttosto complesso. Il loro scopo
principale è quello di permettere la gestione dinamica in run-time degli
oggetti.
EMG

 neanche chiamare linguaggio di programmazione...
In effetti esistono anche linguaggi di programmazione che non permetto
la gestione diretta dei puntatori ma comunque li utilizzano in maniera
implicita per implementare le strutture che rendono esplicite. In fin
dei conti alla base c'è sempre l'ASM che ha nei puntatori il suo pane
quotidiano.
EMG