PDA

Visualizza la versione completa : C++ Puntatori


valder
24-12-2012, 17:08
Salve,avrei qualche domanda riguardo puntatori/vettori/matrici.

Quando chiamo una funzione,e come argomento di questa utilizzo per esempio int *s al posto di int s[],questo comporta qualche differenza?(nel senso,nel primo caso potrò sempre usare s[i] per accedere ai singoli elementi giusto? Perchè il complilatore me lo permette,ma su un altro sito veniva chiaramente detto che era un errore o.O.

Per le matrici(cosa che mi confonde un pò),in un compito ho visto che questa viene chiamata come per i vettori,cioè sempre utilizzando un puntatore come int *s,è giusto?

ed infine,quando si parla di vettori di stringhe,in un compito ho visto veniva chiamata tramite l'utilizzo del doppio puntatore(int **s),mentre in un altro come una matrice(O.o),cioè char vett[][n].
Quindi al momento sono un pò confuso a riguardo xD

Grazie :)

MegaAlchimista
24-12-2012, 19:46
Un vettore sono un insieme di dati, dello stesso tipo, allocati au posizioni contigue della memoria. Quindi in sostanza per accedere ad un vettore l'unica cosa che ti serve avere è un puntatore al primo elemento: dopodichè accedi agli altri elementi avanzando nelle posizioni di memoria che seguono.
Quindi in sostanza se


Char* a;
char v[10];
a = &v[0];
//elemento puntato da a == v[0] == *a;
// a+1 == &v[1]; // algebra dei puntatori
//*(a+1)== v[1];



Per quanto riguarda le matrici: è come se tu avessi un vettore, ma ogni elemento del vettore sia di per se un altro vettore!
Quindi scrivere v[][] è come mettere un doppio puntatore:
char **a;
*a punta ad un char. Se ne allochi n di fila, puoi accedere a tutti.


char*a = new char[10];
È come avere
char a[10];

*(*a) punti ad un'area di memoria, che contiene un puntatore a char
Quindi invece di scrivere
V[][] //che è un vettore di vettori, quindi una matrice
potresti


char stringhe[10][5] //contiene 10 vettori da 5caratteri ognuno.
char** ptr;

E poi vale lo stesso discorso di cui sopra.

Comunque queste cose sono spiegate bene in qualsiasi libro. O comunque decisamente meglio di quanto si possa fare su un forum.
Essendo dei concetti di base ti consiglio di studiarli

Scara95
24-12-2012, 19:46
E' un argomento un po' delicato da trattare in un forum...

Diciamo che int * ed int [] sono intercambiabili...

int ** ed int [][n] sono due cose completamente diverse...

Scara95
24-12-2012, 19:52
@MegaAlchimista, ribadisco che int ** e int [][n] sono 2 cose complentamente diverse.
int ** rappresenta dei jagged arrays: un puntatore ad un'array di puntatori.
int [][n] è invece sì una matrice, ma implementata come un unico blocco di memoria e gestione degli indici in fase di comilazione.
infatti:
a[M][N] è EQUIVALENTE ad a[M*K+N] dove a è tipo a[J][K];

MegaAlchimista
24-12-2012, 19:57
Originariamente inviato da Scara95
@MegaAlchimista, ribadisco che int ** e int [][n] sono 2 cose complentamente diverse.
int ** rappresenta dei jagged arrays: un puntatore ad un'array di puntatori.
int [][n] è invece sì una matrice, ma implementata come un unico blocco di memoria e gestione degli indici in fase di comilazione.
infatti:
a[M][N] è EQUIVALENTE ad a[M*K+N] dove a è tipo a[J][K];
Hai ragione non ricordavo.
Comunque pur essendo diverse dal punto di vista dell'implementazione, possono essere usate entrambe come matrici

Roby.zip
25-12-2012, 02:31
In realtà i puntatori contengono solo un indirizzo di memoria.
A seguito di ciò tra i vari utilizzi degli stessi vi sono le matrici e gli array.
Ma, un int **, è di fatto un puntatore ad un altro puntatore ad intero.
Finchè non viene fatta una malloc (o n + 1 malloc per le matrici), con tanto di casting al tipo di dato a cui deve puntare il puntatore (scusate il bisticcio), non vi è nessun nesso tra puntatori e array o matrici.

Purtroppo spesso anche i professori che spiegano i puntatori fanno fare confusione immischiando concetti diversi.

MItaly
25-12-2012, 02:48
Originariamente inviato da Scara95
Diciamo che int * ed int [] sono intercambiabili...

Per la precisione: nei parametri a funzione sono esattamente la stessa cosa.
Il C e il C++ non supportano il passaggio di array per copia (come invece accade per gli altri tipi) fondamentalmente per ragioni storiche, per cui le seguenti dichiarazioni


void funzione(int a[6]);
void funzione(int a[]);
void funzione(int * a);

sono perfettamente equivalenti, per cui quando passi un array monodimensionale ad una funzione di fatto stai passando un puntatore al suo primo elemento.

La confusione che si fa tra array e puntatori deriva dal fatto che il nome dell'array in praticamente tutti i contesti (se non erro le uniche eccezioni sono gli operatori sizeof e l'operatore & ) decade in un puntatore al primo elemento, su cui poi viene applicato eventualmente l'operatore di indicizzazione [], l'aritmetica dei puntatori o quant'altro.

Un'ottima (anche se un po' complicata) panoramica del funzionamento degli array in C++ e dei più comuni errori si può trovare qui (http://stackoverflow.com/questions/4810664/how-do-i-use-arrays-in-c); ne consiglio la lettura a tutti, anch'io leggendola ho scoperto un mucchio di cose che non ignoravo in materia di array.

Roby.zip
25-12-2012, 03:17
Per la precisione: nei parametri a funzione sono esattamente la stessa cosa. Il C e il C++ non supportano il passaggio di array per copia (come invece accade per gli altri tipi) fondamentalmente per ragioni storiche, per cui le seguenti dichiarazioni

Attenzione però,
se passi un array ad una funzione, puoi modificare tutto il contenuto degli elementi dell'array, ma non il puntatore stesso dell'array che passi.
In C il passaggio è sempre per valore, poichè il valore di un array di fatto è la locazione di memoria del primo elemento, puoi cambiare il contenuto del primo e di tutti gli elementi(ossia i valori puntati) ma non il valore della locazione stessa.
Cioè se all'interno della funzione volessi assegnare un nuovo array al puntatore passato come parametro, questa assegnazione non sarebbe vista al di fuori della funzione.
Per fare ciò devi passare un puntatore del puntatore all'array.

MItaly
25-12-2012, 03:24
Originariamente inviato da Roby.zip
Attenzione però,
se passi un array ad una funzione, puoi modificare tutto il contenuto degli elementi dell'array, ma non il puntatore stesso dell'array che passi.
Certo, infatti quello che ho detto è che non puoi passare un array per valore; quello che dice lo standard infatti è:

any parameter of type “array of T” [...] is adjusted to be “pointer to T”
(C++11, [dcl.fct] ¶5)
e a questo punto valgono le usuali regole di passaggio di parametri, che, come dici, avviene per copia (ovvero, i parametri si comportano come variabili locali che vengono inizializzate ai valori degli argomenti). (C++11, [expr.call] ¶4)

Loading