Newsgroup: it.comp.lang.c++
Titolo: I puntantori..... Cosa sono ? E a cosa servono ?

Salve a tutti, sto imparando a utilizzare il C++, sino adesso sono riuscito
a comprendere abb bene il linguaggio nella sua struttura... ma c'è una cosa
che nn mi è chiara : I puntatori. Vorrei porvi una serie di domande su di
esse.
1 - A cosa servono praticamente ?
2 - Bisogna conoscere i registri di Windows x utilizzarli ?
3 - Xchè le prestazioni aumentano con il loro utilizzo ?
Scusate, anche se vi sembrano domande stupide...io nn riesco ancora
comprenderne il significato. Grazie x la pasienza =),

 2 - Bisogna conoscere i registri di Windows x utilizzarli ?
PERCHE ?!??!?! NO !
Scusa ma non ho tempo per le altre risposte, se non lo fara' nessun altro lo
faro io a breve.
Tommy

 wrote in message
news:ntcS9.63756$Q%4.20...@news1.tin.it...

1) I puntatori servono per poter lavorare a partire dall'indirizzo di una
certa variabile piuttosto che sulla variabile stessa.
Se ad esempio tu dichiari
int count = 0;
int *pcount = &count;
Avrai il valore 5 memorizzato nella variabile count e l'indirizzo dove e'
messa la variabile count viene memorizzato su pcount che e' appunto un
puntatore a interi.
A quale scopo chiedi tu?
Immagina di avere una funzione
void Incrementa(int *p) {*p++;}
Questa funzione ti incrementa il valore contenuto all'indirizzo puntato da
p.
Per cui chiamando Incrementa(pcount);
Quando ritorni dopo la chiamata alla funzione, il valore a cui punta pcount
e cioe' il valore della variabile count sara' incrementato e varra' 1;
Cio' non potevi farlo se avessi definito la funzione
Incrementa(int v) {v++;}
Perche' con la chiamata Incrementa(count); avresti semplicemente copiato il
valore di count sul parametro formale v che sarebbe stato incrementato ma
poi avrebbe perso il suo valore con la fine della funzione avendo uno scope
locale.
Anche in casi in cui non devi modificare valori all'interno di funzioni e'
utile passare puntatori a variabili piuttosto che le variabili stesse,
quando per esempio si tratta di blocchi di dati consistenti (classi,
strutture, array ecc..)
Passando il puntatore passi solo l'indirizzo al blocco di dati e non tutto
il blocco stesso che farebbe diminuire le performances e occuperebbero lo
stack, che e' la parte di memoria che viene impiegata per le variabili
locali e quindi anche al momento della copia dei parametri.
Es:
const int SizeBig = 1000;
class CBig
{
public:
    CBig(); // inizializza l'array big con valori random
private:
    int big[SizeBig];
};
Incrementa(CBig *p)
{
    for (int i = 0; i < SizeBig; i++)
        p->big[i]++;
}
int main()
{
    CBig *p = new CBig();
    Incrementa (p);
    delete p;
    return 0; // nel VisualC++ 6 e' necessario!
}
Quando non hai bisogno di un blocco di dati per tutta la durata del
programma ma solo localmente e poi vorresti liberare la memoria allora e' il
caso di utilizzare l'allocazione dinamica con le new - delete in cui si
usano i puntatori.
Ad esempio se volessi utilizzare un array di 1000 interi  per farci i tuoi
calcoli e poi una volta terminati questi calcoli volessi liberare la memoria
fai una
{
int *pint = new int[1000];
// qua utilizzi pint
for (int i = 0; i < 1000; i++)
    *(pint + i) = i; // oppure pint[i] = i;
// e poi liberi la memoria
delete []pint;
}
2) No non serve conoscere nulla di Windows per utilizzarli. Vengono anche
utilizzati nella programmazione per Windows piuttosto.
3) La prestazione aumenta appunto quando si passa un grosso blocco di dati
per puntatore a una funzione, piuttosto che il grosso blocco stesso.
Esistono anche puntatori a funzioni e i riferimenti (reference) in C++
Maurus

 Esistono anche puntatori a funzioni e i riferimenti (reference) in C++
Volevo inoltre ricordare che i puntatori vengono anche utilizzati per
costruire strutture dati ad esempio, liste, alberi, che troppo spesso non
vengono studiati dagli autodidatti, ma sono fondamentali nell'apprendimento
(almeno).
Quindi Angelo, quando ti senti bravino in C++, dai una occhiata anche a
loro.
Tommy

Grazie sia a Tommy che a Maurus =).
Cmq se ho capito bene (speriamo) i puntatori tornano utili quando si deve
lavorare con variabili piuttosto grosse, e non le si vuole allocare di volta
in volta nello Stack.
Ma si possono anche utilizzare per memorizzare alcuni valori (che magari
vengono spesso utilizzati dal programma) non direttamente in una variabile
(ovvero dichiarando una variabile a assegnargli quindi tale valore) ma
incrementando il puntantore ?
Una altra cosa :  "p->big[i]++;" ... a cosa serve -> ?
Grazie ancora per l'enorme pasienza dimostratami =).
Angelo.

 loro.
In effetti la trattazione di tutti questi argomenti e' lunghina per essere
spiegata in un singolo post,
per cui sarebbe meglio affidarsi a Tutorials specializzati o a libri.
Maurus

 Angelo.
Scusami ma l'esempio che ti avevo dato con CBig aveva un errore in quanto
l'array big era privato alla classe e non poteva essere usato al di fuori di
essa.
Eccoti l'esempio funzionante e modificato che ti mostra che l'istruzione
p->big[i]++ nella funzione Incrementa, serve per incrementare i valori
dell'array big mediante l'accesso col puntatore p.
L'incremento ++ e' riferito ai valori dell'array big che sara' quindi
modificato dalla funzione:
Compila ed esegui questo programma e cosi' verifichi che Show prima
dell'Incrementa ti mostra l'array inizializzato nel costruttore CBig.
Poi l'altro Show ti mostra l'array dopo la modifica della funzione
Incrementa.
// Esempio.cpp
#include <iostream>
const int SizeBig = 10; // non e' tanto big! Ma poi devo stamparlo
class CBig
{
public:
    CBig(); // inizializza l'array big con valori crescenti
    void Show();
    int big[SizeBig];
};
CBig::CBig()
{
   for (int i = 0; i < SizeBig; i++)
      big[i] = i; // 0, 1, 2, ecc..., 9
}
void CBig::Show()
{
// mostra tutto l'array big a schermo
   std::cout << " Big: " << std::endl;
   for (int i = 0; i < SizeBig; i++)
      std::cout << " " << big[i] << " ";
   std::cout << std::endl;
}
void Incrementa(CBig *p)
{
    for (int i = 0; i < SizeBig; i++)
        p->big[i]++; //incrementa i valori di big
// equivale a: p->big[i] = p->big[i] + 1;
}
int main()
{
    CBig *p = new CBig();
    std::cout << "Prima " << std::endl;
    p->Show(); // mostra big prima degli incrementi
    Incrementa (p);
    std::cout << "Dopo " << std::endl;
    p->Show(); // mostra big dopo gli incrementi
    delete p;
    system("PAUSE");
    return 0; // nel VisualC++ 6 e' necessario!
}
Maurus

Grazie per il chiarimento =) adesso kiarisco il mio concetto (speriamo di
riuscirci ;P)
Ad esempio dichiaro una variabile Int è il suo rispettivo puntatore
int a =5;
int* Pa=&a;
ecco, adesso mi ritrovo ad esempio un valore Intero (ad esempio 1000),
invece di fare
int n = 1000;
nn potrei fare così :
Pa+=1;
*Pa = 1000;
in questo modo memorizzo il dato direttamente nella memoria senza creare
un'ulteriore variabile.
Spero di avere kiarito =). Grazie ancora x la pasienza ( nn sono mai
abbastanza =)) )

*Pa = 1000;

 incrementando il puntantore ?
Studiati questo codice:
<CODE>
#include<stdio.h>
int main()
{
    int a=8;
    int *p=&a;
    // indirizzo di a:
    printf("%p\n",&a);
    // indirizzo a cui punta p:
    printf("%p\n",p);
    // incrementiamo il valore di a:
    (*p)++;
    printf("%p - a=%d\n",p,a);
    // incrementiamo indirizzo
    // ora p non puntara' piu'
    // ad a:
    p++;
    printf("%p\n",p);
    return 0;
}
</CODE>
<OUTPUT>
0012FF80
0012FF80
0012FF80 - a=9
0012FF84
Press any key to continue
</OUTPUT>
e risponditi da solo....
Tommy

>Pa+=1;  // perchè aumenti l'indirizzo di Pa di 1?
                                                         ^^^^ in Pa

 *Pa = 1000;
NOOOOO!
e' vero che se Pa punta ad una variabile (in questo caso a), Pa+1 punta ad
una cella di memoria successiva (4 bytes dopo in genere), che potrebbe
essere anche utilizzata... Ma... e se fosse gia' in uso!?!?
Se non lo fosse ma quando poi dichiari successivamente un altra variabile
venisse utilizzata?!?
Guarda questo codice ed il suo output:
<CODE>
#include<stdio.h>
int main()
{
    int a=8;
    int *p=&a;
    printf("%d\n",*p);
    p++;
    *p=45;
    printf("%d\n",*p);
    return 0;
}
</CODE>
<OUTPUT>
8
45
Press any key to continue
<OUTPUT>
Funziona! Non sono sopreso (anche se non e' detto che debba!).
Il fatto che funzioni NON vuole dire che sia corretto anzi.....
Alcuni dei possibili problemi te li ho gia' spiegati prima.
IN SOSTANZA NON FARLO MAI!
Tommy

    ^^^^^
Beh, non era difficile capire cosa volesse fare, rileggi la sua domanda e
guarda la mia risposta.
Ad ogni modo, capisco come mai non hai capito la sua domanda..... e'
completamente sbagliata ed e' una soluzione sporchissima ;-)
Tommy

 grazie x la spiegazione =)
Ti ho risposto anche a quello nel messaggio
news:avbu7q$7aa$
1...@helle.btinternet.com
Ciao
Tommy

 Ke nn punta alla stessa variabile se viene incrementato l'avevo capito,
Congiuntivi a parte che nessuno oramai usa piu', mi chiedo come mai tanta
gente scriva con le 'k' al posto del "ch" ?!?!
Che c**** di mania e' questa ?!?
Tommy

 Che c**** di mania e' questa ?!?
         ^^^
   Che k**** di mania e' questa ?!?
Maurus

aggiornati fratello aggiornati.....uhuhuhuh

cmq (kmq) nn avevo visto il msg in kui lo spiegavo.... errore mio. Grazie
ancora.