PDA

Visualizza la versione completa : benedetti puntatori


roldo
25-02-2012, 15:53
Leggo il forum e so di essere in buona (cattiva) compagnia con chi
ha problemi coi puntatori...ho creduto di capirli tanta volte e altrettante
volte non ne sono uscito.






int main(void) {




char *P[100] = {"gennaio", "febbraio",
"marzo", "aprile",
"", ""};


char *A ;

A = P[3] ;

char **B = &A ;



char * E [5] ;

E[0] = (char*)B ;

printf("%s\n", A);

printf("%s\n", E[0]);



Mi stampa correttamente A
e una porcheria per E[0] ....Perch ?
Grazie.



aprile
'��)�*��PT������`*��PT��
[Press Enter to close window]

SamIam
25-02-2012, 16:06
B un puntatore doppio, quindi devi accedervi tramite un indice :)


E[0] = B[0] ;

oppure


E[0] = (*B) ;


il cast non serve

roldo
25-02-2012, 16:14
Originariamente inviato da SamIam
B un puntatore doppio, quindi devi accedervi tramite un indice :)


E[0] = B[0] ;

oppure


E[0] = (*B) ;


il cast non serve

Grazie ,funziona....Quindi col crescere di livello dei puntatori nascono dei livelli
come fossero vettori di puntatori ?

ardito86
25-02-2012, 16:50
Si, ma pi correttamente si dice "puntatori che a sua volta puntano a puntatori".
Esempio:
char** a;

a un doppio puntatore, e il compilatore sa che a contiene un indirizzo che punta a un altro indirizzo che a sua volta punta a un'altra zona di memoria che contiene un char.


char **B = &A ;
char * E [5] ;
E[0] = *B ;


B un doppio puntatore, e fin qui ci siamo.


Strano a dirlo (non tanto per), anche E un doppio puntatore, perch sappiamo che un array in C non altro che un puntatore al primo elemento dell'array.

Solo che c' una piccola ma sostanziale differenza tra queste due dichiarazioni:
char **B;
char * E [5] ;

La prima semplicemente dichiara un doppio puntatore, mentre la seconda alloca sullo stack 5 puntatori a char. Proprio per il fatto che alloca anche sullo stack, la seconda dichiarazione non molto indicata quando dovrai allocare memoria dinamicamente (per esempio con malloc())

Spero di essertti stato utile

ramy89
25-02-2012, 18:42
L' ho corretto considerando anche l' indentazione, che era un casino:



int main(void)
{
char *P[] = {"gennaio", "febbraio","marzo", "aprile", "", ""};
char *A ;
char **B;
char * E [5] ;
A = P[3] ;
B = &A ;
E[0] = B ;
printf("%s\n", A);
printf("%s\n", *E[0]);
return 0;
}


Se P si trova all' indirizzo mille, ci non ha nessun legame con le stringhe che si trovano in P[0],...,P[5].
Se la stringa P[0] si trova all' indirizzo 2000 nell' area di sola lettura, P contiene l'indirizzo 2000 come valore, ma il puntatore non memorizzato all' indirizzo 2000.
Deferenziando E[0], che contiene l' indirizzo in cui contenuto il puntatore che punta alla stringa P[3], ottieni proprio l' indirizzo della stringa P[3].

ramy89
25-02-2012, 18:56
Originariamente inviato da ardito86
Si, ma pi correttamente si dice "puntatori che a sua volta puntano a puntatori".


E' un vettore di puntatori, non un puntatore a puntatore.
La differenza sostanziale proprio quella che hai detto te, cio che un vettore di puntatori gi allocati nello stack.
Proprio perch il vettore di puntatori gi allocato, non possibile farlo puntare a un' altra area di memoria.
Se invece era un puntatore a puntatore, ci era possibile.
Ad esempio:


char** a; // puntatore a puntatore
char* b[5]; // vettore di puntatori
a=(char**)malloc(5*sizeof(char*));
a[0]=(char*)"ciao";
b=a; // illegale, proprio perch b non un puntatore a puntatore
// ma un array di puntatori, l' array statico

ardito86
25-02-2012, 19:37
Intendevo che riguardo la "grammatica "del linguaggio, un doppio puntatore. Che poi il compilatore tenga conto che stata allocata memoria sullo stack una questione aggiuntiva ...ma

ramy89
25-02-2012, 19:44
Non un doppio puntatore, un indirizzo.Il puntatore assegnabile.
b non assegnabile per cui non un puntatore.

ardito86
26-02-2012, 02:57
Originariamente inviato da ramy89
Non un doppio puntatore, un indirizzo.Il puntatore assegnabile.
b non assegnabile per cui non un puntatore.
Mi dispiace contraddirti...ma un vettore un puntatore.

int a[3];

a un puntatore.

Il fatto che non sia assegnabile che, in questo esempio, il compilatore lo considera come un const int*. Ma un puntatore. Se scrivi in C++:

cout << a;

non ti stamper il vettore m un numeraccio esadecimale che non altro che l'indirizzo in memoria a cui punta.

int *b;
b = a; //lecito

Quindi se io dichiarassi

int* const c;

e facessi:
c=b; //illecito

siccome c non assegnabile allora non un puntatore?

roldo
26-02-2012, 11:06
Continua lo scioglilingua sui puntatori ...e alla fine si in dubbio su un po' di cose.

char *A ; // un puntatore

char **B = &A ; // un puntatore di un puntatore

char ***C = &B ; // un puntatore di un puntatore di un puntatore

Char ****D = &C ; // un puntatore di un puntatore di un puntatore di un puntatore

E cosi all' infinito ?

forse no ...la stringa puntata da A puo essere vista da B solo con

E[0] = (*B) ; oppure E[0] = B[0] ;

sempre la stringa puntata da A posso vederla da C solo con E[1] = (**C) ;

insomma con espressioni strane , mi sembra.....

Loading