Come usare i puntatori C ++

Come usare i puntatori C ++
La memoria di un computer è una lunga serie di celle. La dimensione di ogni cella è chiamata byte. Un byte è uno spazio occupato da un carattere inglese dell'alfabeto. Un oggetto in senso ordinario è un insieme consecutivo di byte in memoria. Ogni cella ha un indirizzo, che è un numero intero, di solito scritto in forma esadecimale. Esistono tre modi per accedere a un oggetto in memoria. È possibile accedere a un oggetto utilizzando quello che è noto come puntatore. È possibile accedervi usando quello che è noto come riferimento. È ancora possibile accedere utilizzando un identificatore. Il focus di questo articolo è sull'uso di puntatori e riferimenti. In C ++, c'è l'oggetto appuntito e l'oggetto puntatore. L'oggetto appuntito ha l'oggetto di interesse. L'oggetto puntatore ha l'indirizzo dell'oggetto appuntito. L'oggetto puntatore e l'oggetto appuntito, ognuno ha il suo identificatore. Devi avere conoscenze di base in C ++, compresi i suoi identificatori, funzioni e array; Per capire questo articolo.

L'operatore dell'indirizzo, e

Questo è un operatore unario. Se seguito da un identificatore, restituisce l'indirizzo dell'oggetto dell'identificatore. Considera la seguente dichiarazione:

int ptdint;

Di seguito è riportato il codice, la seguente espressione, restituirà l'indirizzo identificato da ptdint:

& ptdint

Non è necessario conoscere l'indirizzo esatto (numero) come codice.

L'operatore indirezione, *

Questo è un operatore unario nel contesto di puntatori. Di solito è digitato davanti a un identificatore. Se usato in una dichiarazione dell'identificatore, allora l'identificatore è l'oggetto puntatore che contiene solo l'indirizzo dell'oggetto appuntito. Se usato davanti all'identificatore dell'oggetto puntatore, per restituire qualcosa, allora la cosa restituita è il valore dell'oggetto appuntito.

Creazione di un puntatore

Dai un'occhiata al seguente segmento di codice:

fluttuare ptdfloat;
float *ptrfloat;
ptrfoat = &ptdFloat;

Il segmento inizia con la dichiarazione dell'oggetto appuntito, ptdfloat. Ptdfloat è un identificatore, che identifica solo un oggetto galleggiante. Un oggetto effettivo (valore) avrebbe potuto essere assegnato ad esso, ma in questo caso non è stato assegnato nulla. Successivamente nel segmento, c'è la dichiarazione dell'oggetto puntatore. L'operatore indirezione di fronte a questo identificatore significa che deve contenere l'indirizzo di un oggetto appuntito. Il tipo di oggetto, galleggiante all'inizio dell'istruzione, significa che l'oggetto appuntito è un galleggiante. L'oggetto puntatore è sempre dello stesso tipo dell'oggetto appuntito. PTRFOAT è un identificatore, che identifica solo un oggetto puntatore.

Nell'ultima dichiarazione del codice, l'indirizzo dell'oggetto appuntito viene assegnato all'oggetto puntatore. Nota l'uso dell'operatore di indirizzo, e.

L'ultima istruzione (riga) sopra mostra che dopo aver dichiarato l'oggetto puntatore senza inizializzazione, non è necessario l'operatore indirezione, quando è necessario inizializzarlo. In effetti, è un errore di sintassi utilizzare l'operatore indirezione nella terza linea (ultima).

L'oggetto puntatore può essere dichiarato e inizializzato dall'oggetto appuntito in un'istruzione, come segue:

fluttuare ptdfloat;
float *ptrfoat = &ptdFloat;

La prima riga del segmento di codice precedente e questo è la stessa. La seconda e la terza riga del segmento di codice precedente sono state combinate in un'affermazione qui.

Nota nel codice sopra che quando si dichiara e inizializza l'oggetto puntatore, è necessario utilizzare l'operatore indirezione. Tuttavia, non viene utilizzato se l'inizializzazione deve essere eseguita in seguito. L'oggetto puntatore viene inizializzato con l'indirizzo dell'oggetto appuntito.

Nel seguente segmento di codice, l'operatore indiretto viene utilizzato per restituire il contenuto dell'oggetto appuntito.

int ptdint = 5;
int *ptrint = &ptdInt;
cout << *ptrInt << '\n';

L'output è 5.

Nell'ultima istruzione qui, l'operatore indirezione è stato utilizzato per restituire il valore a cui si è presentato, dall'identificatore del puntatore. Quindi, se utilizzato in una dichiarazione, l'identificatore per l'operatore indiretto avrebbe mantenuto l'indirizzo dell'oggetto appuntito. Se utilizzato in un'espressione di ritorno, in combinazione con l'identificatore del puntatore, l'operatore indirezione restituisce il valore dell'oggetto appuntito.

Assegnare zero a un puntatore

L'oggetto puntatore dovrebbe sempre avere il tipo di oggetto appuntito. Quando si dichiara l'oggetto puntatore, è necessario utilizzare il tipo di dati dell'oggetto appuntito. Tuttavia, il valore di decimale zero può essere assegnato al puntatore come nel seguente segmento di codice:

int ptdint = 5;
int *ptrint;
ptrint = 0;
o nel segmento,
int ptdint = 5;
int *ptrint = 0;

In entrambi i casi, il puntatore (identificatore) è chiamato puntatore nullo; Significa, indica il nulla. Cioè, non ha l'indirizzo di nessun oggetto appuntito. Qui, 0 è decimale zero e non esadecimale zero. Hexadecimal zero indicherebbe il primo indirizzo della memoria del computer.

Non cercare di ottenere il valore indicato da un puntatore nullo. Se lo provi, il programma può compilare, ma potrebbe non eseguire.

Nome dell'array come puntatore costante

Considera il seguente array:

int arr [] = 000, 100, 200, 300, 400;

Il nome dell'array, arr è in realtà l'identificatore che ha l'indirizzo del primo elemento dell'array. La seguente espressione restituisce il primo valore nell'array:

*arr

Con l'array, l'operatore di incremento, ++ si comporta in modo diverso. Invece di aggiungere 1, sostituisce l'indirizzo del puntatore, con l'indirizzo dell'elemento successivo nell'array. Tuttavia, il nome dell'array è un puntatore costante; Significa che il suo contenuto (indirizzo) non può essere modificato o incrementato. Quindi, per incrementare, l'indirizzo iniziale dell'array deve essere assegnato a un puntatore non costante come segue:

int *ptr = arr;

Ora, PTR può essere incrementato per indicare l'elemento successivo dell'array. PTR è stato dichiarato qui come oggetto puntatore. Senza * qui, non sarebbe un puntatore; Sarebbe un identificatore tenere un oggetto int e non tenere un indirizzo di memoria.

Il seguente segmento di codice indica finalmente il quarto elemento:

++PTR;
++PTR;
++PTR;

Il seguente codice emette il quarto valore dell'array:

int arr [] = 000, 100, 200, 300, 400;
int *ptr = arr;
++PTR;
++PTR;
++PTR;
cout << *ptr << '\n';

L'output è 300.

Nome della funzione come identificatore

Il nome di una funzione è l'identificatore della funzione. Considera la seguente definizione della funzione:

int fn ()

cout << "seen" << '\n';
restituzione 4;

FN è l'identificatore della funzione. L'espressione,

& fn

Restituisce l'indirizzo della funzione in memoria. FN è come l'oggetto appuntito. La seguente dichiarazione dichiara un puntatore a una funzione:

int (*func) ();

L'identificatore per l'oggetto appuntito e l'identificatore per l'oggetto puntatore è diverso. func è un puntatore a una funzione. FN è l'identificatore di una funzione. E così, può essere fatto Func per indicare FN come segue:

func = &fn;

Il valore (contenuto) di func è l'indirizzo di FN. I due identificatori avrebbero potuto essere collegati a un'istruzione di inizializzazione come segue:

int (*func) () = &fn;

Nota le differenze e le somiglianze nella gestione dei puntatori della funzione e dei puntatori scalari. Func è un puntatore a una funzione; È l'oggetto appuntito; viene dichiarato in modo diverso da un puntatore scalare.

La funzione può essere chiamata con,

fn ()
O
func ()

Non può essere chiamato con *func ().

Quando la funzione ha parametri, le seconde parentesi hanno i tipi di parametri e non hanno bisogno di avere gli identificatori per i parametri. Il seguente programma illustra questo:

#includere
Utilizzo dello spazio dei nomi std;
float fn (float fl, int in)

ritorno fl;

int main ()

float (*func) (float, int) = &fn;
float val = func (2.5, 6);
cout << val << '\n';
restituzione 0;

L'output è 2.5.

Riferimento C ++

Il riferimento in C ++ è solo un modo per produrre un sinonimo (un altro nome) per un identificatore. Utilizza l'operatore e non allo stesso modo e viene utilizzato per i puntatori. Considera il seguente segmento di codice:

int myint = 8;
int & yourint = myint;
cout << myInt << '\n';
cout << yourInt << '\n';

L'output è:

8
8

La prima affermazione inizializza l'identificatore, Myint; io.e. myint è dichiarato e fatto per contenere il valore, 8. La seconda affermazione rende un nuovo identificatore, il tuo sinonimo di myint. Per raggiungere questo obiettivo, l'operatore e l'operatore è posizionato tra il tipo di dati e il nuovo identificatore nella dichiarazione. Le dichiarazioni Cout mostrano che i due identificatori sono sinonimi. Per restituire il valore in questo caso, non è necessario precederlo con * . Basta usare l'identificatore.

myint e yourint qui, non sono due oggetti diversi. Sono due identificatori diversi che riferiscono (identificando) la stessa posizione in memoria con il valore, 8. Se il valore di myint viene modificato, anche il valore di yourint cambierà automaticamente. Se il valore di yourint viene modificato, anche il valore di myint cambierà automaticamente.

I riferimenti sono dello stesso tipo.

Riferimento a una funzione

Proprio come puoi avere un riferimento a uno scalare, puoi anche avere un riferimento a una funzione. Tuttavia, codificare un riferimento a una funzione è diverso dalla codifica di un riferimento a uno scalare. Il seguente programma illustra questo:

#includere
Utilizzo dello spazio dei nomi std;
float fn (float fl, int in)

ritorno fl;

int main ()

float (& func) (float, int) = fn;
float val = func (2.5, 6);
cout << val << '\n';
restituzione 0;

L'output è 2.5.

Nota la prima affermazione nella funzione principale, che rende Func un sinonimo di FN. Entrambi fanno riferimento alla stessa funzione. Nota l'uso monouso e la posizione di &. Quindi e è l'operatore di riferimento qui e non l'indirizzo di operatore. Per chiamare la funzione, basta usare uno dei due nomi.

Un identificatore di riferimento non è uguale a un identificatore di punta.

Funzione che restituisce un puntatore

Nel seguente programma, la funzione restituisce un puntatore, che è l'indirizzo dell'oggetto appuntito:

#includere
Utilizzo dello spazio dei nomi std;
float *fn (float fl, int in)

float *fll = &fl;
restituire fll;

int main ()

float *val = fn (2.5, 6);
cout << *val << '\n';
restituzione 0;

L'output è 2.5

La prima affermazione nella funzione, fn () è lì solo per creare un oggetto puntatore. Nota la singola usaggio e la posizione di * nella firma della funzione. Nota anche come il puntatore (indirizzo), è stato ricevuto nella funzione principale () da un altro oggetto puntatore.

Funzione che restituisce un riferimento

Nel seguente programma, la funzione restituisce un riferimento:

#includere
Utilizzo dello spazio dei nomi std;
float & fn (float fl, int in)

float & frr = fl;
restituire frr;

int main ()

float & val = fn (2.5, 6);
cout << val << '\n';
restituzione 0;

L'output è 2.5.

La prima istruzione nella funzione, fn () è lì solo per creare un riferimento. Nota la singola uso e la posizione di e nella firma della funzione. Nota anche come il riferimento, è stato ricevuto nella funzione principale () da un altro riferimento.

Passando un puntatore a una funzione

Nel seguente programma, un puntatore, che in realtà è l'indirizzo di un oggetto puntato float, viene inviato come argomento alla funzione:

#includere
Utilizzo dello spazio dei nomi std;
float fn (float *fl, int in)

restituire *fl;

int main ()

float v = 2.5;
float val = fn (& v, 6);
cout << val << '\n';
restituzione 0;

L'output è 2.5

Nota l'uso e la posizione di * per il parametro float nella firma della funzione. Non appena inizia la valutazione della funzione FN (), viene fatta la seguente dichiarazione:

float *fl = & v;

Entrambi FL e V indicano lo stesso oggetto appuntito che contiene 2.5. *FL alla dichiarazione di restituzione non è una dichiarazione; Significa, il valore dell'oggetto appuntito puntato dall'oggetto puntatore.

Passando un riferimento a una funzione

Nel seguente programma, un riferimento viene inviato come argomento alla funzione:

#includere
Utilizzo dello spazio dei nomi std;
Float fn (float & fl, int in)

ritorno fl;

int main ()

float v = 2.5;
float val = fn (v, 6);
cout << val << '\n';
restituzione 0;

L'output è 2.5

Nota l'uso e la posizione di e per il parametro float nella firma della funzione. Non appena inizia la valutazione della funzione FN (), viene fatta la seguente dichiarazione:

float & fl = v;

Passando un array a una funzione

Il seguente programma mostra come passare un array a una funzione:

#includere
Utilizzo dello spazio dei nomi std;
int fn (int arra [])

restituire arra [2];

int main ()

int arr [] = 000, 100, 200, 300, 400;
int val = fn (arr);
cout << val << '\n';
restituzione 0;

L'output è 200.

In questo programma, è l'array che viene superato. Si noti che il parametro della firma della funzione ha una dichiarazione di array vuota. L'argomento nella chiamata di funzione è solo il nome di un array creato.

Può una funzione C ++ restituire un array?

Una funzione in C ++ può restituire il valore di un array, ma non può restituire l'array. La compilazione del seguente programma si traduce in un messaggio di errore:

#includere
Utilizzo dello spazio dei nomi std;
int fn (int arra [])

restituire arra;

int main ()

int arr [] = 000, 100, 200, 300, 400;
int val = fn (arr);
restituzione 0;

Puntatore di un puntatore

Un puntatore può indicare un altro puntatore. Cioè, un oggetto puntatore può avere l'indirizzo di un altro oggetto puntatore. Devono ancora essere tutti dello stesso tipo. Il seguente segmento di codice illustra questo:

int ptdint = 5;
int *ptrint = &ptdInt;
int ** ptrptrint = &ptrInt;
cout << **ptrptrInt << '\n';

L'output è 5.

Nella dichiarazione di puntatore-pointer, viene utilizzato il doppio *. Per restituire il valore dell'oggetto puntato finale, viene ancora utilizzato il doppio *.

Array di puntatori

Il seguente programma mostra come codificare una matrice di puntatori:

#includere
Utilizzo dello spazio dei nomi std;
int main ()

int Num0 = 000, Num1 = 100, Num2 = 200, Num3 = 300, Num4 = 400;
int *no0 = & num0, *no1 = & num1, *no2 = & num2, *no3 = & num3, *no4 =&num4;
int *arr [] = no0, no1, no2, no3, no4;
cout << *arr[4] << '\n';
restituzione 0;

L'output è:

400

Nota l'uso e la posizione di * nella dichiarazione dell'array. Nota l'uso di * Quando si restituisce un valore nell'array. Con i suggerimenti di puntatori, due * sono coinvolti. Nel caso di una serie di puntatori, uno * è già stato curato, perché l'identificatore dell'array è un puntatore.

Array di stringhe a lunghezza variabile

Una stringa letterale è una costante che restituisce un puntatore. Un array di stringhe a lunghezza variabile è una matrice di puntatori. Ogni valore nell'array è un puntatore. I puntatori sono indirizzi a posizioni di memoria e hanno le stesse dimensioni. Le stringhe delle diverse lunghezze sono altrove in memoria, non nell'array. Il seguente programma illustra l'uso:

#includere
Utilizzo dello spazio dei nomi std;
int main ()

const char *arr [] = "donna", "ragazzo", "ragazza", "adulto";
cout << arr[2] << '\n';
restituzione 0;

L'output è "ragazza".

La dichiarazione dell'array inizia con la parola riservata, "const" per costante; seguito da "char" per il personaggio, quindi l'asterisco, * per indicare che ogni elemento è un puntatore. Per restituire una stringa dall'array, * non viene utilizzata, a causa della natura implicita del puntatore di ciascuna stringa. Se * viene utilizzato, verrà restituito il primo elemento della stringa.

Puntatore a una funzione che restituisce un puntatore

Il seguente programma illustra come viene codificato un puntatore a una funzione che restituisce un puntatore:

#includere
Utilizzo dello spazio dei nomi std;
int *fn ()

int num = 4;
int *inter = #
RITORNO Inter;

int main ()

int *( *func) () = &fn;
int val = *func ();
cout << val << '\n';
restituzione 0;

L'output è 4.

La dichiarazione di un puntatore a una funzione che restituisce un puntatore è simile alla dichiarazione di un puntatore a una funzione normale ma preceduta con un asterisco. La prima affermazione nella funzione principale () illustra questo. Per chiamare la funzione usando il puntatore, precederlo con *.

Conclusione

Per creare un puntatore a uno scalare, fai qualcosa di simile,

galleggiante appuntito;
Float *puntatore = &pointed;

* ha due significati: in una dichiarazione, indica un puntatore; Per restituire qualcosa, è per il valore dell'oggetto appuntito.

Il nome dell'array è un puntatore costante al primo elemento dell'array.

Per creare un puntatore a una funzione, puoi farlo,

int (*func) () = &fn;

dove fn () è una funzione definita altrove e il func è il puntatore.

& ha due significati: in una dichiarazione, indica un riferimento (sinonimo) allo stesso oggetto di un altro identificatore; Quando si restituisce qualcosa, significa l'indirizzo di.

Per creare un riferimento a una funzione, puoi farlo,

float (& reffunc) (float, int) = fn;

dove fn () è una funzione definita altrove e il reffunc è il riferimento.

Quando una funzione restituisce un puntatore, il valore restituito deve essere ricevuto da un puntatore. Quando una funzione restituisce un riferimento, il valore restituito deve essere ricevuto da un riferimento.

Quando si passa un puntatore a una funzione, il parametro è una dichiarazione, mentre l'argomento è l'indirizzo di un oggetto appuntito. Quando si passa un riferimento a una funzione, il parametro è una dichiarazione, mentre l'argomento è il riferimento.

Quando si passa un array a una funzione, il parametro è una dichiarazione mentre l'argomento è il nome dell'array senza []. La funzione C ++ non restituisce un array.

Un puntatore a pointer necessita di due * anziché uno, ove appropriato.