Pagina 1 di 3

Puntatori chiarimenti [risolto]

Inviato: gio 9 lug 2020, 12:50
da SlackNewbie
Salve :)
Ho iniziato lo studio dei puntatori in C però ho un dubbio al livello teorico,mi spiego meglio.
Dichiaro una variabile di tipo intero ed un puntatore a questa variabile:

Codice: Seleziona tutto

int num;
int *ptr;
e se volessi chiedere all'utente di inserire un numero intero e salvarlo nella variabile num facendo però uso del puntatore faccio così:
printf("Inserire numero intero:");
scacnf("%d",ptr);
Cosi facendo tramite la varibile di tipo puntatore riesco ad agire sull'indirizzo della variabile num modificandone quindi il valore memorizzato.Giusto??
Ma se volessi,nel codice,fare l'operazione di assegnamento di un numero intero nella variabile num passando però dall'utilizzo della varibile ptr,io farei in questo modo:

Codice: Seleziona tutto

ptr=7;
E questo perchè tramite la variabile puntatore riesco ad agire direttamente all'indirizzo della variabile num modificandone il valore che vi è memorizzato.
Questa cosa però è sbagliata :( e non capisco il perchè!!!
Invece si fa così:

Codice: Seleziona tutto

*ptr=7;
Con la scritta *ptr non dovrei ottenere il valore che vi è memorizzato nella variabile num(cioè al suo indirizzo) e quindi la scrittura precedente è come se fosse:
5=7
dove 5 è il valore precedente già salvato(presente) nella variaible num.
Mah.....
Attendo delucidazioni.
Ringrazio anticipatamente :)

Re: Puntatori chiarimenti

Inviato: gio 9 lug 2020, 15:19
da targzeta
Con ptr=7 stai modificando il valore del puntatore. Il puntatore non è altro che un'area di memoria il cui valore è l'indirizzo dell'area di memoria che ti interessa. Con quell'assegnamento tu stai facendo puntare ptr all'area di memoria 7, che probabilmente non è neanche tua e quindi vai in segfault.
Con *ptr invece è come se dicessi "l'area di memoria puntata da ptr". Quindi, a tutti gli effetti, cambi il valore che ti interessa.

Emanuele

Re: Puntatori chiarimenti

Inviato: gio 9 lug 2020, 17:59
da SlackNewbie
Ciao targzeta e grazie per avermi risposto!!!
Ma una variabile di tipo puntatore, ad esempio,in questo caso,puntatore ad intero contiene solo l'indirizzo di una variabile oppure tramite questa variaible puntatore è possibile agire direttamente sul contenuto della variabile a cui punta??
Non so se sono riuscito a spiegarmi...
E quindi se io memorizzo in una variabile di tipo puntatore l'indirizzo della variaible num allora potrei agire su quest'ultima(cioè sul valore presente al suo indirizzo) tramite il puntatore.Giusto??
E perciò un eventuale assegnamento di un valore alla variabile num di tipo int lo potrei fare sfruttando la variabile puntatore:

Codice: Seleziona tutto

int num;
int *ptr;
ptr=#
ptr=5;
printf("Valore della variabile num:%d",*ptr);
giusto??Però cosi il compilatore mi da errore...mah
Oppure far inserire direttamente dall'utente:

Codice: Seleziona tutto

int num;
int *ptr;
ptr=#
printf("Inserisci numero intero:");
scanf("%d",ptr);
printf("Valore inserito é:%d",*ptr);  //stessa cosa otterei se facessi---------> printf("Valore inserito:%d",num);
Altra domanda:che differenza< vi è tra
int *ptr;
come dichiarazione di una variabile di tipo puntatore ed quando invece uso *ptr nel prosieguo del codice?

Re: Puntatori chiarimenti

Inviato: ven 10 lug 2020, 0:29
da targzeta
Certo che puoi modificare il valore della variabile puntata. Proprio fancendo la dereferenziazione *ptr. Devi leggere *ptr come "la variabile puntata da ptr". Così ti risulta semplice capire che *ptr=5 vuol dire "assegna 5 alla variabile puntata da ptr", che è come dire "assegna 5 a num".

Fare ptr=5 non ha nessun nenso, perché stai dicendo che ptr deve puntare alla locazione di memoria 5.

In pratica, modificare ptr vuol dire modificare l'indirizzo a cui ptr punta, mentre modificare *ptr vuol dire modificare il contenuto dell'indirizzo puntato.

Non so spiegartelo meglio, mi spiace. Il contenuto di ptr è un indirizzo, il contenuto di *ptr è il contenuto dell'indirizzo scritto dentro ptr.

Emanuele

Re: Puntatori chiarimenti

Inviato: ven 10 lug 2020, 12:28
da SlackNewbie
Ciao targzeta e grazie per la risposta.
Bene, credo di aver capito: se assegno un qualcosa alla variabile ptr vado quindi a modificare il suo contenuto e cioè un indirizzo di una qualche tipo di variabile;allora giustamente la scrittura
ptr=5;
non ha senso!!!
Invece,fare
ptr=&num;
ha senso perchè assegno l'indirizzo della variabile num alla varibile puntatore.Perciò:
*ptr=5 si legge "assegno 5 alla varibile puntata da ptr"
Ossia se uso direttamente la variabile ptr per un qualche assegnamento,così facendo vado a modificare l'indirizzo a cui la variabile puntatore va a puntare.
Invece con*ptr modifico il contenuto presente a quell'indirizzo.
Domanda:con la scanf perchè si scrive:
scanf("%d",&num); o anche,facendo uso del puntatore
scanf("%d",ptr)????

Re: Puntatori chiarimenti

Inviato: ven 10 lug 2020, 15:06
da ilmich
SlackNewbie ha scritto:
ven 10 lug 2020, 12:28
Domanda:con la scanf perchè si scrive:
scanf("%d",&num); o anche,facendo uso del puntatore
scanf("%d",ptr)????
perchè in c quando passi i parametri ad una funzione il passaggio avviene per valore (a differenza di altri linguaggi dove avviene per riferimento).
In altre parole in c quando invochi una funzione passi una 'copia' del valore e non il suo riferimento.
questo in molte circostanze va anche bene, ma se per i tuoi scopi la variabile passata in input la devi modificare (come nel caso della scanf) se non passassi il puntatore la funzione produrrebbe risultati errati

Re: Puntatori chiarimenti

Inviato: ven 10 lug 2020, 16:08
da targzeta
Considera che &num e ptr contengono lo stesso valore, ovvero l'indirizzo in memoria della variabile num. Ti torna?

Emanuele

Re: Puntatori chiarimenti

Inviato: ven 10 lug 2020, 17:50
da SlackNewbie
Salve :)
Ciao ilmich e grazie per l'attenzione.
Ho capito il concetto,ho però un dubbio e cioè su molti libri di testo,a proposito delle funzioni, si dice che in C il passaggio di parametri può avvenire in due modi ossia o per valore o per riferimento.
Invece il prof durante il corso ci ha detto che il C prevede come passaggio di parametri ad una funzione solo il passaggio per valore.
Possiamo dire che in effetti che in C le funzioni ammettono il passaggio di parametri solo per valore tuttavia grazie all'esistenza delle variabili di tipo puntatori si riesce ad effettuare il passaggio per parametri anche per indirizzo e che quindi ciò è possibile grazie all'esistenza di questo tipo di variabili.
E' giusta questa affermazione??
Ringrazio anche te targzeta per l'aiuto :thumbright:
Un ultimissimo dubbio che mi è venuto:guardando un video tutorial sui puntatori,ad un certo punto,viene creato un puntatore ad un puntatore ad intero.
Scrivo il codice che forse è meglio:

Codice: Seleziona tutto

int num;
int *ptr;
int** ptr1;
ptr=&num;
ptr1=&ptr;
printf("Inserire numero intero:");
scanf("%d",ptr1);
printf("Il numero inseritro è :%d",*ptr1);
Nel tutorial però il codice non viene eseguito ed il video finisce...Ho provato ad eseguire io il codice però ottengo errore.
Praticamente quello che si vuole fare è scrivere all'indirizzo della variabile (di tipo intero) num tramite un puntatore che punta ad un puntatore in cui è presente l'indirizzo di num...A me il discorso sembra filare...però ottengo errore!!!!
Potete chiarirmi questo fatto??

Re: Puntatori chiarimenti

Inviato: ven 10 lug 2020, 18:38
da targzeta
Esatto, dato che hai un puntatore, la copia del puntatore che si becca la funzione, punterà sempre alla stessa locazione del tuo puntatore originale. Così, ad esempio, invece di passare ad una funzione una struttura grande di diversi byte (che verrebbe copiata e passata alla funzione), gli passi un puntatore alla struttura, che contiene solo l'indirizzo di dove comincia.

Per l'altra questione, invece, visto che dici di aver capito il concetto di puntatore, dovresti anche capire perché il tuo codice non funziona! La scanf con %d vuole come argomento un puntatore ad un intero, non mi sembra che tu gli abbia passato questo!

Emanuele

Re: Puntatori chiarimenti

Inviato: ven 10 lug 2020, 19:00
da SlackNewbie
Ciao targzeta e grazie come sempre !!!
Dovrei scrivere
scanf("%p",ptr1);
Giusto?? :oops:
Ho errore con il seguente codice però:

Codice: Seleziona tutto

int main()
{
    int num;
    int *ptr;
    int **ptr1;
    ptr=&num;
    ptr1=&ptr;
    printf("\nInserisci un numero intero:");
    scanf("%p",ptr1);
    printf("\nIl numero inserito risulta:%p",*ptr1);
    printf("\n\n%d",num);
    return 0;
in particolare,riesco a compilare ma ottengo risultati sbagliati!!!
Quello che voglio fare è modificare il valore contenuto all'indirizzo della variabile num passando per un puntatore che punta alla variabile num.

Re: Puntatori chiarimenti

Inviato: sab 11 lug 2020, 20:33
da brg
Il codice non ha senso. La variabile ptr1 è usata come puntatore a puntatore, quindi

Codice: Seleziona tutto

scanf("%p",ptr1);
si aspetta che l'utente inserisca un indirizzo di memoria, non un numero intero qualsiasi.
Così la variabile num non è inizializzata.

Re: Puntatori chiarimenti

Inviato: dom 12 lug 2020, 11:21
da SlackNewbie
Salve !!!
Ciao brg e grazie per la risposta.
Quello che vorrei fare è assegnare un numero ,chiedendo all'utente di inserirlo,lla variabile num passando per l'utilizzo di un puntatore ad un punttaore alla variabile num.
Però mi sono perso....Aiuto!!!

Re: Puntatori chiarimenti

Inviato: dom 12 lug 2020, 11:53
da brg
Be', non ha molto senso comunque:

Codice: Seleziona tutto

scanf("%d",*ptr1);

Re: Puntatori chiarimenti

Inviato: dom 12 lug 2020, 18:26
da SlackNewbie
Ciao brg :)
Dunque con
scanf("%d",*ptr1);
dovrei riuscire a scrivere all'indirizzo della variabile num??
E per stampare il valore,sfruttando sempre la variabile ptr1,basta fare cosi:

Codice: Seleziona tutto

printf("%d",*ptr1);
??
Il discorso non mi quadra più... :oops:
E se volessi generalizzare ed cioè far uso di un puntatore ad un puntatore ad un puntatore ......ecc. che punta alla variaible num per modificare il valore di quest'ultima??

Re: Puntatori chiarimenti

Inviato: dom 12 lug 2020, 22:37
da albatros
Ciao, prova a dare un'occhiata al codice seguente, spero ti aiuti a capire meglio il giochino:

Codice: Seleziona tutto

#include<stdio.h>
int main()
{
    int num=-999;
    int *ptr;
    int **ptr1;
    ptr=&num;
    ptr1=&ptr;
    printf("La variabile num è memorizzata all'indirizzo %p, ha valore: %d, e occupa %ld bytes\n",&num, num, sizeof(num));
    printf("La variabile ptr è un puntatore a un intero. ptr è memorizzata all'indirizzo %p, ha valore %p (la posizione in memoria di num) e occupa %ld bytes. Il valore puntato da ptr vale: %d\n",&ptr,ptr,sizeof(ptr),*ptr);
    printf("La variabile ptr1 è un puntatore a un puntatore a un intero. ptr1 è memorizzata all'indirizzo %p, ha valore %p (la posizione in memoria di ptr) e occupa %ld bytes.\n", &ptr1, ptr1, sizeof(ptr1));
    printf("Con *ptr1 estraggo il valore di quanto puntato da ptr1, che è a sua volta un indirizzo di memoria e vale: %p.\nCon **ptr1 ottengo il valore di quanto memorizzato in quest'ultimo indirizzo di memoria, che è un intero e che vale: %d\n",*ptr1,**ptr1);
    printf("\nInserisci un numero intero:  ");
    scanf("%d",*ptr1);
    printf("\nAggiornamento della situazione:\n");
    printf("La funzione scanf ha memorizzato il valore che hai inserito nell'indirizzo di memoria fornito come argomento, ossia %p\n", *ptr1);
    printf("La variabile num è sempre memorizzata all'indirizzo %p, ma adesso ha valore: %d\n",&num, num);
    printf("La variabile ptr è sempre memorizzata all'indirizzo %p, ha valore %p e il valore da lei puntato vale: %d\n",&ptr,ptr,*ptr);
    printf("La variabile ptr1 è sempre memorizzata all'indirizzo %p e ha sempre valore %p.\n", &ptr1, ptr1);
    printf("Il valore puntato ptr1 vale sempre %p, mentre il valore puntato dall'indirizzo di memoria puntato da ptr1, che è un intero, vale ora: %d e coincide con il valore puntato da ptr:%d\n",*ptr1,**ptr1,*ptr);

    return 0;
}
Dovresti ottenere, eseguendo il programma, qualcosa tipo:

La variabile num è memorizzata all'indirizzo 0x7ffcde61a094, ha valore: -999, e occupa 4 bytes
La variabile ptr è un puntatore a un intero. ptr è memorizzata all'indirizzo 0x7ffcde61a098, ha valore 0x7ffcde61a094 (la posizione in memoria di num) e occupa 8 bytes. Il valore puntato da ptr vale: -999
La variabile ptr1 è un puntatore a un puntatore a un intero. ptr1 è memorizzata all'indirizzo 0x7ffcde61a0a0, ha valore 0x7ffcde61a098 (la posizione in memoria di ptr) e occupa 8 bytes.
Con *ptr1 estraggo il valore di quanto puntato da ptr1, che è a sua volta un indirizzo di memoria e vale: 0x7ffcde61a094.
Con **ptr1 ottengo il valore di quanto memorizzato in quest'ultimo indirizzo di memoria, che è un intero e che vale: -999

Inserisci un numero intero: 45

Aggiornamento della situazione:
La funzione scanf ha memorizzato il valore che hai inserito nell'indirizzo di memoria fornito come argomento, ossia 0x7ffcde61a094
La variabile num è sempre memorizzata all'indirizzo 0x7ffcde61a094, ma adesso ha valore: 45
La variabile ptr è sempre memorizzata all'indirizzo 0x7ffcde61a098, ha valore 0x7ffcde61a094 e il valore da lei puntato vale: 45
La variabile ptr1 è sempre memorizzata all'indirizzo 0x7ffcde61a0a0 e ha sempre valore 0x7ffcde61a098.
Il valore puntato ptr1 vale sempre 0x7ffcde61a094, mentre il valore puntato dall'indirizzo di memoria puntato da ptr1, che è un intero, vale ora: 45 e coincide con il valore puntato da ptr:45