Puntatori chiarimenti [risolto]

Forum dedicato alla programmazione.

Moderatore: Staff

Regole del forum
1) Citare in modo preciso il linguaggio di programmazione usato.
2) Se possibile portare un esempio del risultato atteso.
3) Leggere attentamente le risposte ricevute.
4) Scrivere i messaggi con il colore di default, evitare altri colori.
5) Scrivere in Italiano o in Inglese, se possibile grammaticalmente corretto, evitate stili di scrittura poco chiari, quindi nessuna abbreviazione tipo telegramma o scrittura stile SMS o CHAT.
6) Appena registrati è consigliato presentarsi nel forum dedicato.

La non osservanza delle regole porta a provvedimenti di vari tipo da parte dello staff, in particolare la non osservanza della regola 5 porta alla cancellazione del post e alla segnalazione dell'utente. In caso di recidività l'utente rischia il ban temporaneo.
SlackNewbie
Linux 1.x
Linux 1.x
Messaggi: 154
Iscritto il: dom 30 dic 2012, 15:01

Puntatori chiarimenti [risolto]

Messaggio 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 :)
Ultima modifica di SlackNewbie il lun 20 lug 2020, 11:46, modificato 1 volta in totale.

Avatar utente
targzeta
Iper Master
Iper Master
Messaggi: 6629
Iscritto il: gio 3 nov 2005, 14:05
Nome Cognome: Emanuele Tomasi
Slackware: 64-current
Kernel: latest stable
Desktop: IceWM
Località: Carpignano Sal. (LE) <-> Pisa

Re: Puntatori chiarimenti

Messaggio 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
Se pensi di essere troppo piccolo per fare la differenza, prova a dormire con una zanzara -- Dalai Lama

SlackNewbie
Linux 1.x
Linux 1.x
Messaggi: 154
Iscritto il: dom 30 dic 2012, 15:01

Re: Puntatori chiarimenti

Messaggio 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=&num;
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=&num;
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?

Avatar utente
targzeta
Iper Master
Iper Master
Messaggi: 6629
Iscritto il: gio 3 nov 2005, 14:05
Nome Cognome: Emanuele Tomasi
Slackware: 64-current
Kernel: latest stable
Desktop: IceWM
Località: Carpignano Sal. (LE) <-> Pisa

Re: Puntatori chiarimenti

Messaggio 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
Se pensi di essere troppo piccolo per fare la differenza, prova a dormire con una zanzara -- Dalai Lama

SlackNewbie
Linux 1.x
Linux 1.x
Messaggi: 154
Iscritto il: dom 30 dic 2012, 15:01

Re: Puntatori chiarimenti

Messaggio 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)????

ilmich
Master
Master
Messaggi: 1645
Iscritto il: lun 16 lug 2007, 17:39
Slackware: 15.0 64bit
Kernel: 5.15.27
Desktop: kde
Località: Roma

Re: Puntatori chiarimenti

Messaggio 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
#LiveSimple and #ProgramThings
https://github.com/ilmich
http://ilmich6502.it/

Avatar utente
targzeta
Iper Master
Iper Master
Messaggi: 6629
Iscritto il: gio 3 nov 2005, 14:05
Nome Cognome: Emanuele Tomasi
Slackware: 64-current
Kernel: latest stable
Desktop: IceWM
Località: Carpignano Sal. (LE) <-> Pisa

Re: Puntatori chiarimenti

Messaggio da targzeta »

Considera che &num e ptr contengono lo stesso valore, ovvero l'indirizzo in memoria della variabile num. Ti torna?

Emanuele
Se pensi di essere troppo piccolo per fare la differenza, prova a dormire con una zanzara -- Dalai Lama

SlackNewbie
Linux 1.x
Linux 1.x
Messaggi: 154
Iscritto il: dom 30 dic 2012, 15:01

Re: Puntatori chiarimenti

Messaggio 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??

Avatar utente
targzeta
Iper Master
Iper Master
Messaggi: 6629
Iscritto il: gio 3 nov 2005, 14:05
Nome Cognome: Emanuele Tomasi
Slackware: 64-current
Kernel: latest stable
Desktop: IceWM
Località: Carpignano Sal. (LE) <-> Pisa

Re: Puntatori chiarimenti

Messaggio 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
Se pensi di essere troppo piccolo per fare la differenza, prova a dormire con una zanzara -- Dalai Lama

SlackNewbie
Linux 1.x
Linux 1.x
Messaggi: 154
Iscritto il: dom 30 dic 2012, 15:01

Re: Puntatori chiarimenti

Messaggio 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.

Avatar utente
brg
Linux 3.x
Linux 3.x
Messaggi: 580
Iscritto il: sab 12 mar 2011, 14:20
Slackware: 15.0
Kernel: 5.15.117
Desktop: KDE5
Località: Montecatini
Contatta:

Re: Puntatori chiarimenti

Messaggio 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.

SlackNewbie
Linux 1.x
Linux 1.x
Messaggi: 154
Iscritto il: dom 30 dic 2012, 15:01

Re: Puntatori chiarimenti

Messaggio 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!!!

Avatar utente
brg
Linux 3.x
Linux 3.x
Messaggi: 580
Iscritto il: sab 12 mar 2011, 14:20
Slackware: 15.0
Kernel: 5.15.117
Desktop: KDE5
Località: Montecatini
Contatta:

Re: Puntatori chiarimenti

Messaggio da brg »

Be', non ha molto senso comunque:

Codice: Seleziona tutto

scanf("%d",*ptr1);

SlackNewbie
Linux 1.x
Linux 1.x
Messaggi: 154
Iscritto il: dom 30 dic 2012, 15:01

Re: Puntatori chiarimenti

Messaggio 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??

Avatar utente
albatros
Iper Master
Iper Master
Messaggi: 2093
Iscritto il: sab 4 feb 2006, 13:59
Kernel: 5.19.0
Desktop: gnome and lxqt
Distribuzione: ubuntu 22.04
Località: Darmstadt - Germania

Re: Puntatori chiarimenti

Messaggio 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

Rispondi