[C] Dubbio puntatori

Messaggioda studente-studente » 26/10/2016, 19:01

Buonasera sto approfondendo i puntatori, sto iniziando ad intuire le potenzialità super affascinanti di come posso evitare di sovradimensionare matrici, passare parametri, manipolare strutture dati ed altro.. però leggendo il libro ho trovato due piccoli esempi che mi hanno completamente resettato tutto quello che ho capito sugli indirizzi e operatori.

Il primo esempio, molto chiaro sarebbe: (dentro il main eh)
Codice:
int a;
int *aPtr; //aPtr e' un puntatore a un intero

a=7;
aPtr=&a; //imposta aPtr all'indirizzo di a
printf ("%p %p", &a, aPtr);
printf("%d %d", a, *aPtr);
}


Dove si vede che: a e *aPtr cioè il contenuto della cella puntata dal puntatore stampano lo stesso risultato in quanto stiamo parlando dello stesso contenuto mentre &a e aPtr stampano l'indirizzo proprio perché "dentro" il puntatore si ha l'indirizzo.

Il problema sta nell'esempio 2 quando spiega il passaggio per riferimento:
Codice:
#include <stdio.h>

void cubeByReference (int *nPtr);
int main(void){
     int numero=5;
     cubeByReference(&numero);
}

void cubeByReference (int *nPtr){
     *nPtr=*nPtr* *nPtr * *nPtr;
}


Ma se la funzione si aspetta un puntatore, perché non passo un puntatore ma un indirizzo? Cioè ho capito che il puntatore al suo interno ha salvato l'indirizzo di una variabile e di conseguenza punta a quella.. ma quando noi abbiamo una funzione che si aspetta int N gli do un numero int non altro.. spero di essermi spiegato.. probabilmente è una cavolata ma proprio non riesco a trovare un motivo: perché oltre numero non si dichiara un puntatore che punta a numero e passa quello?

Inoltre, da quello che ho capito (ormai ho messo tutto in dubbio :roll: ) il linguaggio C non prevede il passaggio per riferimento ma solo per valori..Allora quando noi usiamo i puntatori non è per riferimento (?) ma nemmeno per valore, come lo definiamo? stiamo praticamente raggirando il C?!

Grazie in anticipo per le vostre eventuali e pazienti risposte
studente-studente
Junior Member
Junior Member
 
Messaggio: 49 di 472
Iscritto il: 13/07/2016, 21:43

Re: [C] Dubbio puntatori

Messaggioda vict85 » 26/10/2016, 22:03

La frase
studente-studente ha scritto:il linguaggio C non prevede il passaggio per riferimento ma solo per valori..Allora quando noi usiamo i puntatori non è per riferimento
mi fa pensare che
  1. Tu venga da altri linguaggi,
  2. Tu non comprenda fino in fondo cosa significa passare per riferimento.

Il C passa tranquillamente oggetti per riferimento (in realtà non possiede il tipo reference, ma in un certo senso un reference è soltanto un particolare tipo di puntatore). Quando tu passi qualcosa per riferimento, tu stai passando alla funzione l'indirizzo in memoria di quel particolare oggetto. In C questo procedimento richiede una operazione esplicita da parte del programmatore. Questo non è vero invece in altri linguaggi. L'unica eccezione a questo, nel C, è data dagli array che sono sempre passati per riferimento.

Detto questo ogni cosa che viene passata ad una funzione occupa una particolare locazione di memoria locale della funzione e possiede un certo valore. Quindi, in un certo senso, per il C, non vi è alcune differenza tra passare direttamente ad una funzione l'indirizzo di un particolare oggetto oppure passare per valore un puntatore che contiene l'indirizzo di quel particolare oggetto. In entrambi i casi la funzione possiederà un oggetto di tipo puntatore che contiene al suo interno il valore numerico corrispondente all'indirizzo in memoria della variabile in questione. Non so se mi sono spiegato bene. Relativamente a questo aspetto c'è anche quello che passare per puntatore potrebbe non ridurre la memoria utilizzata dalla funzione se il valore a cui punta ha una dimensione inferiore a quella di un puntatore (cosa che in una programma a 64 bite è quasi vera per quasi tutti i tipi primitivi).
vict85
Moderatore
Moderatore
 
Messaggio: 8908 di 19253
Iscritto il: 16/01/2008, 00:13
Località: Berlin

Re: [C] Dubbio puntatori

Messaggioda apatriarca » 27/10/2016, 11:14

L'argomento viene passato per valore anche quando stai passando un puntatore. Il valore in questo caso non è infatti l'oggetto a cui il puntatore sta puntando, ma il puntatore stesso. Stai insomma copiando un indirizzo. Il risultato è del tutto equivalente al passaggio per riferimento dell'oggetto a cui il puntatore sta puntando (ed è in effetti come viene implementato tale passaggio in altri linguaggi) ma dal punto di vista teorico si tratta pur sempre di un passaggio per valore. Quel puntatore può in effetti essere modificato senza fare mai riferimento al valore a cui il puntatore sta puntando. Considera il seguente esempio:
Codice:
int *mid(int *a, int *b) {
    return a + (b - a)/2;
}

Restituisce l'indirizzo ad un intero intermedio tra due puntatori a e b. L'intero codice funziona anche se a e b puntano a memoria non valida (anche se in questo caso il comportamento potrebbe non essere del tutto sensato).
apatriarca
Moderatore
Moderatore
 
Messaggio: 4442 di 10436
Iscritto il: 08/12/2008, 20:37
Località: Madrid

Re: [C] Dubbio puntatori

Messaggioda studente-studente » 28/10/2016, 18:09

vict85 ha scritto:Il C passa tranquillamente oggetti per riferimento (in realtà non possiede il tipo reference, ma in un certo senso un reference è soltanto un particolare tipo di puntatore). Quando tu passi qualcosa per riferimento, tu stai passando alla funzione l'indirizzo in memoria di quel particolare oggetto. In C questo procedimento richiede una operazione esplicita da parte del programmatore.


Sinceramente io avevo capito, esattamente come ha detto apatriarca, che il C prevede il passaggio di parametri solo per valore in modo tale che il programma che chiama la funzione non veda le modifiche fatte al suo interno e che il linguaggio C appiana questa ""mancanza"" passando, sempre per valore, i puntatori alle variabili. E questa cosa mi sembra quello che poi hai cercato di spiegarmi dopo: (giusto?)

vict85 ha scritto: Quindi, in un certo senso, per il C, non vi è alcune differenza tra passare direttamente ad una funzione l'indirizzo di un particolare oggetto oppure passare per valore un puntatore che contiene l'indirizzo di quel particolare oggetto. In entrambi i casi la funzione possiederà un oggetto di tipo puntatore che contiene al suo interno il valore numerico corrispondente all'indirizzo in memoria della variabile in questione. Non so se mi sono spiegato bene.
studente-studente
Junior Member
Junior Member
 
Messaggio: 51 di 472
Iscritto il: 13/07/2016, 21:43

Re: [C] Dubbio puntatori

Messaggioda vict85 » 28/10/2016, 18:26

Io e Antonio diciamo la stessa cosa. Passare per riferimento significa che la funzione possiede l'indirizzo della variabile memorizzata in qualche variabile locale alla funzione (o un qualche altro modo per recuperare l'indirizzo). Questo è vero a livello di eseguibile, indipendentemente dal linguaggio utilizzato. I linguaggi in cui si passano oggetti per riferimento ti nascondono questo comportamento. Un'altra differenza tra il C e i linguaggi che permettono il passaggio per riferimento è che il C non ti assicura che l'indirizzo sia valido (né al momento in cui questo viene inviato alla funzione né durante la funzione stessa). Altri linguaggi, invece, ti assicurano che certe cose non possano succedere (il cosa ti viene assicurato dipende dal linguaggio).
vict85
Moderatore
Moderatore
 
Messaggio: 8909 di 19253
Iscritto il: 16/01/2008, 00:13
Località: Berlin

Re: [C] Dubbio puntatori

Messaggioda studente-studente » 28/10/2016, 18:49

Vi ringrazio per i vostri chiarimenti ma, ahimè, ancora non riesco a connettere ](*,) :
Perché se mi aspetto un puntatore io passo l'indirizzo?

Ad esempio, perché non faccio così:
Codice:
#include <stdio.h>

void cubeByReference (int *nPtr);

int main (void) {

   int numero=5;
   int *numPtr; //puntatore che puntera' a un valore intero

   numPtr=&numero;
   cubeByReference(*numPtr);
}

void cubeByReference (int *nPtr){
     *nPtr=*nPtr* *nPtr * *nPtr;
}


Spero di essermi fatto comprendere..
studente-studente
Junior Member
Junior Member
 
Messaggio: 52 di 472
Iscritto il: 13/07/2016, 21:43

Re: [C] Dubbio puntatori

Messaggioda apatriarca » 28/10/2016, 20:20

cubeByReference vuole come argomento qualcosa di tipo int *. Non puoi passargli qualcosa di tipo int senza aspettarti qualche problema.. Per quanto riguarda il codice dentro cubeByReference ci metterei qualche parentesi o userei una variabile temporanea.
apatriarca
Moderatore
Moderatore
 
Messaggio: 4443 di 10436
Iscritto il: 08/12/2008, 20:37
Località: Madrid

Re: [C] Dubbio puntatori

Messaggioda studente-studente » 28/10/2016, 20:32

Credo di aver capito: la funzione vuole il tipo int* , ovvero vuole una variabile di tipo puntatore a int ma passandogli *numPtr è come se passassi proprio numero visto che è numero l'elemento puntato. Allora passo l'indirizzo dato che la variabile di tipo puntatore a int numPtr=&numero..

Ah finalmente l'ho capito come funziona eheh i puntatori mi confondono, credo di doverci prendere la mano!
Grazie mille per le vostre risposte, buona serata.
studente-studente
Junior Member
Junior Member
 
Messaggio: 53 di 472
Iscritto il: 13/07/2016, 21:43

Re: [C] Dubbio puntatori

Messaggioda Super Squirrel » 28/10/2016, 23:47

Ma se la funzione si aspetta un puntatore, perché non passo un puntatore ma un indirizzo?


In realtà la funzione fun(int*) non si aspetta una variabile puntatore ad int, ma l'indirizzo di memoria di un intero. Così come la funzione fun(int) non si aspetta una variabile int, ma un intero. Poi ovviamente puoi anche passare una variabile che contenga il tipo di dato che la funzione si aspetta, ossia una variabile puntatore a int nel primo caso e una variabile int nel secondo.

Considera la seguente porzione del tuo codice

Codice:
cubeByReference(*numPtr);


Il programma si aspetta l'indirizzo di memoria di un intero, ma tu gli passi un intero. Secondo me dovresti rivedere la differenza del simbolo * nelle dichiarazioni di una variabile puntatore e come operatore di dereferenziazione.
Prova a lanciare il seguente codice:

Codice:
#include <iostream>

using namespace std;

int main()
{
    int n = 5;
    int* p = &n;
    cout <<  n << " - " << &n << endl;
    cout << *p << " - " <<  p;
}
Chi dorme in democrazia, si sveglia in dittatura.
Super Squirrel
Senior Member
Senior Member
 
Messaggio: 96 di 1486
Iscritto il: 16/05/2013, 22:05

Re: [C] Dubbio puntatori

Messaggioda studente-studente » 29/10/2016, 06:51

Super Squirrel ha scritto: In realtà la funzione fun(int*) non si aspetta una variabile puntatore ad int, ma l'indirizzo di memoria di un intero. Così come la funzione fun(int) non si aspetta una variabile int, ma un intero. [...]

Considera la seguente porzione del tuo codice

Codice:
cubeByReference(*numPtr);


Il programma si aspetta l'indirizzo di memoria di un intero, ma tu gli passi un intero. Secondo me dovresti rivedere la differenza del simbolo * nelle dichiarazioni di una variabile puntatore e come operatore di dereferenziazione.


Buongiorno, ho seguito il tuo consiglio e rivisto un attimino i puntatori.. pensavo di aver capito :cry:
Allora quando io scrivo int *Ptr posso dire due cose (uguali): Ptr è una variabile di tipo puntatore ad un intero oppure che il dato che viene puntato da Ptr è un intero.

Se io scrivo che la fun(int*) posso dire che la funzione si aspetta una di quelle due cose.

Perciò quando io faccio
Codice:
int *Ptr;
Ptr=&num

ho che dentro la variabile puntatore ad intero Ptr si trova il puntatore a num, il suo indirizzo.
Quindi a fun(int*) gli passo il Ptr cioè &num.. quindi alla fine l'indirizzo..

Super Squirrel ha scritto:Poi ovviamente puoi anche passare una variabile che contenga il tipo di dato che la funzione si aspetta, ossia una variabile puntatore a int nel primo caso e una variabile int nel secondo.


E allora fun(&num) sarebbe uguale a fun(Ptr) no?

Quindi, in conclusione, cosa ho sbagliato? Ieri sera mi pare di aver detto la stessa cosa di ora (quindi o ancora sbatto la testa al muro oppure ieri ho spiegato male)
studente-studente
Junior Member
Junior Member
 
Messaggio: 54 di 472
Iscritto il: 13/07/2016, 21:43

Prossimo

Torna a Informatica

Chi c’è in linea

Visitano il forum: Nessuno e 1 ospite