- Fondamentalmente puntatore è una variabile utilizzata per memorizzare l'indirizzo della memoria, che è sempre
esadecimale (indirizzo di memoria) allora perché dobbiamo tipo di dati differente per la memorizzazione dell'indirizzo. - EX: int * a; Possiamo usarlo a per memorizzare l'indirizzo float.
risposta
Non tutti i puntatori sono (necessari per essere) della stessa dimensione. Se si dispone di una struttura di grandi dimensioni che deve essere allineata a 10 MB, il compilatore potrebbe decidere di avere solo 8 bit (anziché i soliti 32 o 64) per archiviare tutti gli indirizzi possibili su cui potrebbe essere posizionata la variabile.
Inoltre non è necessario necessario un diverso tipo di dati, è possibile utilizzare void*
bene, ma perché vuoi? In C++, questo è un odore di codice.
C'è anche la sicurezza del tipo. Conosci uno int*
punti a un int
e questo è a tuo vantaggio.
L'aritmetica del puntatore può anche essere un vantaggio? –
Perché fornisce informazioni su come interpretare i dati puntati dal puntatore.
EX: int * a; Possiamo usarlo a per memorizzare l'indirizzo float.
Attraverso tipo C caratteristica insicurezza: sì, ma non direttamente, soprattutto negli ultimi compilatori e di serie (che tendono a essere più sicuro e più sicure)
Due motivi:
Su alcune architetture i puntatori possono avere formati diversi a seconda delle dimensioni dei dati a cui puntano. Ad esempio, un puntatore a
char
deve essere in grado di indirizzare singoli byte, ma un puntatore aint
deve essere in grado di indirizzare gruppi di 4 byte. Quindi quest'ultimo potrebbe utilizzare un formato contenente l'indirizzo di byte diviso per 4.Consente al compilatore di generare i programmi corretti. Se si tenta di annullare la corrispondenza di un puntatore
char
e assegnarlo aint
, è necessario sapere che deve solo leggere un byte dall'origine e allargarlo alla dimensione di unoint
. Senza la dichiarazione del tipo di puntatore, leggerebbe più byte del necessario.
Per cominciare, non so di una macchina in cui i puntatori sono memorizzati come esadecimale; ogni macchina con cui ho familiarità utilizzava una rappresentazione binaria internamente. (Per gli ultimi 30 o 40 anni, almeno. IIRC, l'IBM 1401 utilizzato decimali ovunque.)
Come altri hanno fatto notare, non tutti i puntatori fare hanno lo stesso dimensioni e la rappresentazione. Ho lavorato su macchine in cui char*
era più grande di altri tipi di puntatori di dati e, naturalmente, avere dimensioni diverse per i puntatori di funzione e i puntatori di dati utilizzati per essere molto comuni.
La risposta reale, tuttavia, si basa sul sistema di tipi in C e C++. Se p
è un puntatore, qual è il tipo di *p
? Se scrivo qualcosa come *p + *q
, il compilatore deve sapere se usare l'aritmetica dei numeri interi o dell'aritmetica in virgola mobile, ad esempio .
Per quanto riguarda la seconda domanda: in genere, sì, anche se probabilmente loprobabilmente avrà bisogno di un reinterpret_cast
da qualche parte. Tuttavia, l'unica cosa che puoi fare legalmente con il tuo int*
è castata a indietro a float*
; il dereferenziamento è un comportamento indefinito.
Esistono alcune eccezioni per char*
e unsigned char*
. E in pratica, se si sa cosa si sta facendo, è possibile ottenere via con le cose come:
float f;
int* a = reinterpret_cast<int*>(&f);
std::cout << *a << std::endl;
Io in realtà fare cose simili per alcuni tipi di basso livello debug o di programmazione; cose come estrarre il campo esponente da un float
. Tale codice è estremamente raro, tuttavia, e implica formalmente un comportamento non definito, quindi è necessario verificare cosa fa effettivamente il compiler e, eventualmente, disattivare determinate ottimizzazioni .
Perché abbiamo bisogno di tipo di dati diversi per la memorizzazione di indirizzo
Questa è in realtà la domanda corretta, e la risposta è nascosto in essa - Perché abbiamo bisogno di un tipo di dati diverso per memorizzare indirizzi. Noi (i programmatori) ne abbiamo bisogno. Alla macchina non importa: un numero è uguale all'altro.
Se si pensa a una "variabile" come "segnaposto" per alcuni dati, esiste una dicotomia nei linguaggi di programmazione tra l'utilizzo dei dati stessi e l'utilizzo della variabile. A volte hai bisogno solo dei dati (ad es. Devi stamparlo) ea volte hai bisogno dell'indirizzo in cui sono archiviati questi dati (ad es. Puoi modificarlo). La maggior parte delle lingue ha zucchero sintattico che confonde questi due casi e tratta l'identificatore di variabile in modi diversi in contesti diversi.
Uno di questi casi è questa: prendere in considerazione la dichiarazione
a = 1;
In questo caso, il compilatore ricerca l'indirizzo di una variabile identificata da "a", e scrive "1" a questo indirizzo. L'identificatore "a" potrebbe anche essere un puntatore. Ora guarda a una cosa diversa:
if (a == 1) ... ;
Sei non confrontando l'indirizzo di una variabile identificata da "a" con qualcosa, si sta confrontando ciò che è conservato a questo indirizzo con "1".
I vari "tipi di puntatore" esistono di nuovo per comodità del programmatore: è fondamentalmente in modo che creiamo meno errori accedendo in modo errato ai dati.Guarda questo esempio:
double d;
double* dp;
int i;
int* ip;
Per impostazione predefinita, C è molto rilassato su di esso, e di solito si può fare un:
dp = ip;
o
dp = &i;
... ma! sizeof (i) == 4 e sizeof (d) == 8, quindi se si denota il puntatore dp si cercherebbe di leggere 8 byte da una variabile (i) che ne contiene solo 4. Ciò significa che si leggerà 4 imprevedibili byte (casuali) dopo i primi quattro byte di i, che è sicuramente qualcosa che non si vuole fare.
Ancora una volta, tutto questo è per la nostra comodità. Alla macchina non interessa Entrambi i puntatori appaiono e si comportano esattamente allo stesso modo della CPU.
- 1. perché abbiamo bisogno di np.squeeze()?
- 2. Perché abbiamo bisogno di Control.Lens.Reified?
- 3. Perché abbiamo bisogno di "Tipi di dati algebrici"?
- 4. perché abbiamo bisogno di Hadoop per Hypertable
- 5. Perché abbiamo bisogno di un tag fieldset?
- 6. Perché abbiamo bisogno fibre
- 7. Perché abbiamo bisogno di WCF
- 8. Perché abbiamo bisogno di un registro stackpointer quando abbiamo già il registro del contatore del programma?
- 9. Perché abbiamo bisogno di un pool di connessioni per JDBC?
- 10. Perché abbiamo bisogno di Anaconda quando abbiamo pip?
- 11. Perché abbiamo bisogno di endianness qui?
- 12. Perché abbiamo bisogno di un quarto costruttore per Lollipop?
- 13. Perché abbiamo bisogno di altre lingue JVM
- 14. Perché abbiamo bisogno di funcall in Lisp?
- 15. Perché abbiamo bisogno di JWT quando abbiamo sessioni client?
- 16. Perché abbiamo bisogno di costruttori statici?
- 17. Abbiamo bisogno di un iPhone/iPad per il suo sviluppo?
- 18. perché abbiamo bisogno di ClassMethods e InstanceMethods?
- 19. perché abbiamo bisogno di zone_highmem su x86?
- 20. Perché abbiamo bisogno di typename qui?
- 21. Perché abbiamo bisogno di scalaz.stream su iteratee?
- 22. Perché abbiamo bisogno di questo speciale operatore ===?
- 23. Perché abbiamo bisogno di ng-clic?
- 24. Perché abbiamo bisogno di pull per aggiornare l'app mobile?
- 25. Che tipo di macchina abbiamo bisogno per lo sviluppatore C#
- 26. Perché abbiamo bisogno di SocketOptions.SO_BROADCAST per abilitare la trasmissione?
- 27. Quando abbiamo bisogno di un .template costruire
- 28. Abbiamo veramente bisogno di "oauth_nonce"?
- 29. Perché abbiamo bisogno di più di un manifest per il progetto Android?
- 30. Perchè abbiamo bisogno di dnx o multipiattaforma per il web
"indirizzo di memoria, che è sempre esadecimale" No. Questo dipende dalla rappresentazione, che si trova su un altro livello. – glglgl
Durante la ricerca sul Web, ho ottenuto [Perché diversi tipi di puntatori per tipi diversi di dati in c] (http://stackoverflow.com/questions/12530806/why-different-types-of-pointer-for-different-data-type- in-c) –
beh, la rappresentazione non è mai visibile ... –