Puntatore a puntatore in C++

Puntatore A Puntatore In C



Questo articolo riguarda il concetto di puntatore a puntatore in C++. Il puntatore a puntatore punta o memorizza l'indirizzo di un altro puntatore e consente la manipolazione dei puntatori stessi. Usando questo concetto, possiamo facilmente modificare un puntatore da un'altra posizione nella memoria. I puntatori doppi sono utili nella memoria allocata dinamicamente o negli array multidimensionali per manipolare gli elementi di un array. Discuteremo il funzionamento e l'utilizzo di questo puntatore a puntatore in C++ con esempi appropriati.

Scenario 1:  Rappresentazione in memoria di puntatore a puntatore

In questo scenario, la dichiarazione del doppio puntatore è simile alla dichiarazione del puntatore con un asterisco aggiuntivo (*) prima del nome del puntatore. Possiamo facilmente rappresentare la posizione di memoria di un doppio puntatore in C++. Lo snippet di codice del puntatore a puntatore è riportato di seguito:







#include
utilizzando lo spazio dei nomi std;
int principale ( )
{
cifra intera  = cinquanta ;
int * prr;
prr = & cifra;
int ** ptrr1;
ptrr1 = & prr;
cout << 'L'indirizzo di memoria del puntatore è: \N ' ;
cout << 'ptrr (puntatore): ' << ptrr << ' \N ' ;
cout << '*ptrr1 (doppio puntatore): ' <<* ptrr1 << ' \N ' ;
cout << ' Il valore memorizzato nel puntatore è: \N ' ;
cout << '*ptrr = ' <<* ptrr << fine;
cout << '**ptrr1 (puntatore a puntatore) = ' <<** ptrr1 << fine;
ritorno 0 ;
}


Nella funzione main, prendiamo una variabile il cui indirizzo di memoria deve essere memorizzato in un puntatore. Ora inizializziamo la variabile “digit”. Successivamente, dichiariamo il puntatore 'ptrr' che memorizza l'indirizzo di memoria 'cifra'. Ora dichiariamo il doppio puntatore il cui nome è “**ptrr1” che memorizza l'indirizzo del puntatore “*ptrr”. Alla fine del codice, visualizziamo la memoria e il valore del puntatore e del doppio puntatore sullo schermo della console. L'output di questo codice è menzionato di seguito:




L'indirizzo di memoria del puntatore 'ptrr' è '0x6ffe04' e il puntatore '*ptrr1' memorizza anche l'indirizzo di memoria del puntatore 'ptrr'. Il valore memorizzato all'interno del puntatore è “50”. Fondamentalmente l'indirizzo del doppio puntatore è sempre lo stesso dell'indirizzo di memoria del puntatore.



Scenario 2:  puntatore a puntatore come parametro di funzione

In questo scenario impareremo come passare il doppio puntatore in qualsiasi funzione come parametro per eseguire l'allocazione temporanea della memoria in qualsiasi variabile. Lo snippet di codice del parametro funzione con doppio puntatore è menzionato di seguito:





#include
void getMemoryAddress ( int ** double_ptr ) {
il tuo tempo = 200 ;
* double_ptr = & temperatura;
}

int principale ( ) {
int * ptr_1;
int ** double_ptr;
double_ptr = & ptr_1;
getMemoryAddress ( double_ptr ) ;
std::cout << 'Il valore di **double_ptr è: ' << ** double_ptr << std::endl;
ritorno 0 ;
}


Qui impareremo come funziona il concetto di puntatore a puntatore in C++. Ricordare che un puntatore è dichiarato nel programma per funzionare con un puntatore doppio. Quindi, creiamo la funzione “getMemoryAddress”. Progettiamo questa funzione in modo che quando passiamo il parametro, ottenga automaticamente l'indirizzo di memoria del doppio puntatore.

Nella funzione prendiamo la variabile “tempp” e il doppio puntatore “**double_ptr”. Passiamo l'indirizzo della variabile specificata che è 'tempp' al puntatore doppio e i valori del puntatore doppio come argomento della funzione. Il programma visualizza il risultato del codice della funzione principale sullo schermo della console, quindi tutte le cose presenti nella funzione principale sono eseguibili. Prendiamo il puntatore 'ptr_1' e il puntatore double come 'double_ptr' nella funzione principale. Passiamo l'indirizzo del puntatore al doppio puntatore.



Ora passiamo la variabile puntatore doppio nella funzione di override e passiamo il puntatore alla variabile puntatore nell'istruzione del flusso di output 'cout' per mostrare il risultato del puntatore doppio.

Quando il compilatore raggiunge la funzione di override, il controllo del compilatore in cui è definita questa funzione esegue il codice all'interno della funzione e restituisce il risultato alla funzione principale.

L'output di questo codice è allegato di seguito:


Risultato: il valore del puntatore doppio è 200.

Scenario 3:  utilizzo dell'array 2D con puntatore a puntatore

In questo esempio, ci occuperemo di un array 2D avente un doppio puntatore. Prendiamo un array e passiamo l'indirizzo di un array nel puntatore. Il codice completo di questo scenario è fornito come segue:

int principale ( ) {
const int righe = 3 ;
const int cols = 2 ;
int ** matrice = nuovo int * [ righe ] ;
per ( int io = 0 ; io < righe; ++i ) {
matrice [ io ] = nuovo interno [ col ] ;
}
per ( int io = 0 ; io < righe; ++i ) {
per ( int j = 0 ; J < col; ++j ) {
matrice [ io ] [ J ] = io * cols + j;
}
}
per ( int io = 0 ; io < righe; ++i ) {
per ( int j = 0 ; J < col; ++j ) {
cout << matrice [ io ] [ J ] << ' ' ;
}
cout << fine;
}
per ( int io = 0 ; io < righe; ++i ) {
eliminare [ ] matrice [ io ] ;
}
eliminare [ ] matrice;
ritorno 0 ;
}


Come tutti sappiamo, in un array 2D abbiamo molte righe e diverse colonne. Nella funzione main inizializziamo le righe e le colonne che hanno 'const int'. Successivamente, assegniamo lo spazio di memoria per le righe e lo spazio di memoria per le colonne lungo ogni riga. Passiamo il valore del numero di righe come puntatore nella matrice doppio puntatore come “**matrix”. In questo doppio puntatore, il ciclo del numero di righe viene eseguito o è vero. Quindi, viene eseguito un altro ciclo interno finché la condizione non diventa falsa.

Dopo l'allocazione della memoria, assegniamo nuovamente un valore in un array: un ciclo esterno per le righe e un ciclo interno per le colonne dell'array 2D. Nel ciclo interno, il valore di righe e colonne viene assegnato al doppio puntatore ed esegue l'operazione aritmetica richiesta. Visualizziamo i valori di un array 2D come il numero di righe e colonne allocate nella memoria. Il numero di righe e colonne punta sempre al doppio puntatore che memorizza i valori di righe e colonne. Alla fine, liberiamo la memoria e deallochiamo questo array dalla memoria in C++.

L'output dell'array 2D con un doppio puntatore è allegato di seguito:

Scenario 4: scambio di puntatori utilizzando puntatore a puntatore

Qui impareremo come scambiare i puntatori in C++ dichiarando il doppio puntatore. Lo snippet di codice di questo scenario è allegato di seguito:

#include
scambio nullo ( int ** ptrr_1, tu ** ptrr_2 ) {
int * temp_var = * ptrr_1;
* ptrr_1 = * ptrr_2;
* ptrr_2 = var_temp;
}
int principale ( ) {
intero x = quindici , y = 25 ;
int * ptrrA = & X, * ptrrB = & E;
std::cout << 'Prima dello scambio: *ptrrA è = ' << * ptrrA << ', *ptrrB è = ' << * ptrrB << std::endl;
scambio ( & ptrrA, & ptrrB ) ;
std::cout << 'Dopo lo scambio: *ptrrA  is = ' << * ptrrA << ', *ptrrB  is= ' << * ptrrB << std::endl;
ritorno 0 ;
}


Per prima cosa costruiamo la funzione swap, passando entrambi i puntatori come argomento della funzione. Nella funzione swap, prendiamo il puntatore “temp” e passiamo il valore di “pointer1” in “temp” per un po’ di tempo. Quindi, passiamo il valore di “pointer2” a “pointer1”. Alla fine, passiamo il valore del puntatore “temp” al “pointer2”.

Nella funzione main abbiamo bisogno di due puntatori che passiamo o sovrascriviamo nella funzione “swap”. Passiamo gli indirizzi delle variabili ai puntatori dati. Quindi, viene visualizzato il valore del puntatore prima e dopo lo scambio del puntatore.

L'output di questo codice è allegato di seguito:


Come possiamo vedere, i valori del puntatore vengono scambiati con successo utilizzando un doppio puntatore in C++.

Conclusione

Abbiamo concluso che il puntatore a puntatore memorizza sempre l'indirizzo di memoria di qualsiasi puntatore in C++. Possiamo utilizzare il doppio puntatore per utilizzare temporaneamente la posizione di memoria di qualsiasi puntatore in qualsiasi momento. Questo è un modo molto efficace per manipolare indirettamente l'indirizzo di memoria e avvicinarsi ai dati.