2015-09-27 17 views
6

Sto imparando i puntatori e mi è stato detto questo: "Lo scopo dei puntatori è quello di consentire all'utente di accedere direttamente a un blocco di memoria."Cosa può fare un puntatore che una variabile non può fare?

Dire che ho int var = 5;. Non posso usare la variabile 'var' per accedere al blocco di memoria in cui è memorizzato il valore 5, dal momento che posso modificare il valore della variabile ogni volta che voglio var = 6;? Ho davvero bisogno di un puntatore quando posso accedere a qualsiasi valore di una variabile semplicemente utilizzando la sua variabile, invece di usare un puntatore che punta all'indirizzo in cui è memorizzato il valore?

+0

L'importante nozione è quella di [puntatore aliasing] (https://en.wikipedia.org/wiki/Pointer_aliasing) –

+0

Correlati: http: // stackoverflow.com/q/27484168/694576 – alk

+1

"Lo scopo dei puntatori è quello di consentire all'utente di accedere direttamente a un blocco di memoria." è un po 'una strana affermazione; Direi che l'uso principale per i puntatori per situazioni in cui non si ha il nome della variabile disponibile (ad esempio l'implementazione del riferimento pass-by o l'accesso a oggetti allocati dinamicamente o l'accesso al membro di un array con l'indice mutevole) –

risposta

1

tipi puntatore hanno alcune caratteristiche che li rendono molto utili:

  1. 'garantito che un puntatore sarà così grande che può contenere qualsiasi indirizzo che è supportato dall'architettura (x86, cioè 32 bit alias 4 byte e un x64 64 bit alias 8 byte).
  2. Il dereferenziazione e l'indicizzazione della memoria vengono eseguite per oggetto, non per byte.

    int buffer[10]; 
    char*x = buffer; 
    int*y = (int*)buffer; 
    

In questo modo, x [1] non è y [1]

Entrambi non è garantito se si utilizzano semplici int s per tenere i vostri valori. La prima caratteristica è almeno garantita da uintptr_t (non da size_t, sebbene, sebbene la maggior parte delle volte abbiano le stesse dimensioni - eccetto che size_t può avere una dimensione di 2 byte su sistemi con layout di memoria segmentato, mentre uintptr_t ha ancora 4 byte di dimensione).

Durante l'utilizzo int s potrebbe funzionare in un primo momento, è sempre:

  1. devono trasformare il valore in un puntatore
  2. devono dereference il puntatore
  3. e fare in modo che don' andare oltre certi valori per il tuo "puntatore". Per un 16 bit int, non puoi andare oltre 0xFFFF, per 32 bit è 0xFFFF FFFF - una volta fatto, il puntatore potrebbe traboccare senza che te ne accorga fino a quando non è troppo tardi.

Questo è anche il motivo per cui le liste collegate e puntatori a tipi incompleti lavoro - il compilatore sa già la dimensione dei puntatori che si sta per voi, e solo alloca la memoria per loro. Tutti i puntatori hanno la stessa dimensione (4 o 8 byte su architetture a 32-bit/64-bit) - il tipo che li assegna semplicemente dice al compilatore come dereferenziare il valore. char* s occupano lo stesso spazio di void* s, ma non è possibile annullare la chiamata void* s. Il compilatore non ti lascerà.

Inoltre, se hai a che fare con interi semplici, c'è una buona possibilità che tu rallenti il ​​tuo programma in modo significativo a qualcosa chiamato "aliasing", che fondamentalmente costringe il compilatore a leggere il valore di un dato indirizzo tutto il tempo. Gli accessi alla memoria sono lenti, quindi si desidera ottimizzare questi accessi alla memoria.

+0

Questo sembra manca il problema piuttosto più fondamentale, ovvero che i puntatori consentono di accedere a un oggetto senza conoscere il nome della variabile associata a quell'oggetto. –

+0

Sei andato oltre ciò che l'OP sta chiedendo. – edmz

1

È possibile confrontare un indirizzo di memoria a un indirizzo stradale:

Se si ordina qualcosa, vi dico il negozio vostro indirizzo, in modo che possano inviare quello che hai comprato. Se non si desidera utilizzare il proprio indirizzo, è necessario inviare loro la casa, in modo che possano inserire il pacco all'interno. Più tardi ti restituiscono la casa. Questo è un po 'più ingombrante di usare l'indirizzo!
Se non sei a casa, il pacco può essere consegnato al tuo vicino se hanno il tuo indirizzo, ma questo non è possibile se lo ti ha inviato la tua casa invece.

Lo stesso vale per i puntatori: sono piccoli e possono essere trasportati facilmente, mentre l'oggetto che indicano potrebbe essere grande e meno facilmente trasportabile.
Con l'aritmetica del puntatore, i puntatori possono anche essere utilizzati per accedere ad altri oggetti rispetto a quello che avevano inizialmente indicato.

1

Si chiama una funzione da main() o da un'altra funzione, la funzione chiamata può solo restituire 1 valore. Diciamo che vuoi cambiare 3 valori, li passi alla funzione chiamata come puntatori. In questo modo non devi usare valori globali.

+0

Si potrebbe anche restituire una struttura. –

1

"Lo scopo dei puntatori è quello di consentire all'utente di accedere direttamente a un blocco di memoria."

Questo non è sempre vero. Considerare

*(int*)(0x1234) = some_value; 

questo è l'accesso alla memoria "diretto". Anche se

int a = some_value, *ptr = &a; 
*ptr = some_other_value; 

ora si sta accedendo aindirettamente.

non riesco ad utilizzare la variabile 'var' per accedere al blocco di memoria in cui è memorizzato il valore 5 , dato che posso cambiare il valore della variabile ogni volta che voglio var = 6; ?

Sicuramente; ma la semantica è diversa.

Ho davvero bisogno di un puntatore quando posso accedere a qualsiasi valore di una variabile semplicemente utilizzando la sua variabile, invece di utilizzare un puntatore che punta all'indirizzo in cui è memorizzato il valore?

No, non è così. Considera il primo esempio: all'interno dello scope in cui è stato dichiarato a, la modifica del suo valore tramite ptr è piuttosto inutile! Tuttavia, cosa succede se non si è nell'ambito di a? Questo è

void foo(int x) 
{ 
    x = 5; 
} 

int main(void) 
{ 
    int x = 10; 
    foo(x); 
} 

In foo, quando lo fai x = 5, c'è un'ambiguità: vuoi modificare o foo::xmain::x? In quest'ultimo caso, è necessario "esplicitamente" richiesto e il fatto che ciò avvenga tramite i puntatori - o meglio, tramite indiretta - è una coincidenza e una scelta di lingua. Altre lingue hanno altri.

Problemi correlati