2009-12-04 19 views
169

Che cos'è uintptr_t e a cosa può essere utilizzato?Che cos'è uintptr_t tipo di dati

+5

Ulteriori dettagli su questo tipo così come altri tipi correlati è disponibile qui: http://www.opengroup.org/onlinepubs/000095399/basedefs/stdint.h.html – Void

+0

http: //en.cppreference .com/w/cpp/types/integer elenca 'std :: uintptr_t' e' std :: intptr_t' a C++ 11 opzionale. – alfC

risposta

127

È un int unsigned che è in grado di memorizzare un puntatore. Il che significa in genere che ha le stesse dimensioni di un puntatore.

È facoltativamente definito in C++ 11 e standard successivi.

Un motivo comune per desiderare un tipo intero che può contenere il tipo di puntatore di un'architettura è eseguire operazioni specifiche di un intero su un puntatore o oscurare il tipo di puntatore fornendolo come un "handle" intero.

Edit: Si noti che Steve Jessop ha alcuni dettagli aggiuntivi molto interessanti (che non voglio rubare) in another answer here per voi tipi pedanti :)

+40

Nota che 'size_t' deve essere sufficiente per contenere la dimensione dell'oggetto più grande e può essere più piccolo di un puntatore. Ci si aspetterebbe su architetture segmentate come l'8086 (16 bit 'size_t', ma 32 bit' void * ') – MSalters

+2

per rappresentare la differenza tra due puntatori, si ha' ptrdiff_t'. 'uintptr_t' non è pensato per quello. – jalf

+3

@jalf: per differenza, sì, ma per * distanza *, si desidera un tipo senza segno. –

16

Si tratta di digitare un numero intero senza segno esattamente la dimensione di un puntatore. Ogni volta che devi fare qualcosa di insolito con un puntatore, ad esempio invertire tutti i bit (non chiedere perché), devi lanciarlo su uintptr_t e manipolarlo come un normale numero intero, quindi eseguire il cast back.

+5

Ovviamente lo si potrebbe fare, ma ovviamente sarebbe un comportamento indefinito. Credo che quindi l'unica cosa che puoi fare con il risultato di un cast su uintptr_t è di passarlo invariato e restituirlo - tutto il resto è UB. – sleske

+0

Ci sono momenti in cui è necessario giocare con i bit e normalmente genererebbe errori del compilatore. Un esempio comune è l'applicazione della memoria allineata a 16 byte per determinate applicazioni video e prestazioni critiche. http://stackoverflow.com/questions/227897/solve-the-memory-alignment-in-c-interview-question-that-stumped-me – DevNull

+3

@sleske non è vero. Sulle macchine con tipi auto allineati i due bit meno significativi di un puntatore saranno pari a zero (poiché gli indirizzi sono multipli di 4 o 8). Ho visto programmi che sfruttano questo per comprimere i dati .. – saadtaame

183

Per prima cosa, al momento della domanda, uintptr_t non era in C++. È in C99, in <stdint.h>, come tipo facoltativo. Molti compilatori C++ 03 forniscono quel file. È anche in C++ 11, in <cstdint>, dove ancora è facoltativo e che si riferisce a C99 per la definizione.

In C99, è definito come "un numero intero senza segno con la proprietà che qualsiasi puntatore valido a void può essere convertito in questo tipo, quindi riconvertito in puntatore a vuoto e il risultato verrà confrontato uguale al puntatore originale ".

Prendi questo per indicare ciò che dice. Non dice nulla riguardo alle dimensioni.

uintptr_t potrebbe essere la stessa dimensione di void*. Potrebbe essere più grande. Potrebbe essere concepibilmente più piccolo, anche se una simile implementazione in C++ si avvicina alla perversione. Ad esempio, su alcune piattaforme ipotetiche in cui void* è a 32 bit, ma vengono utilizzati solo 24 bit di spazio di indirizzi virtuali, è possibile disporre di un uintptr_t a 24 bit che soddisfi i requisiti. Non so perché un'implementazione lo farebbe, ma lo standard lo consente.

+4

Grazie per "". La mia applicazione non è stata compilata a causa della dichiarazione uintptr_t. Ma quando leggo il tuo commento aggiungo "#include " e sì, ora funziona. Grazie! – JavaRunner

+1

Perché qualcuno dovrebbe voler lanciare un puntatore su int? –

+2

Per [allocare memoria allineata] (http://stackoverflow.com/q/227897/183120), tra gli altri usi, ad esempio? – legends2k

6

Ci sono già molte buone risposte alla parte "che cos'è uintptr_t tipo di dati". Proverò ad affrontare "cosa può essere usato?" parte in questo post.

Principalmente per operazioni bit a bit sui puntatori. Ricorda che in C++ non è possibile eseguire operazioni bit a bit sui puntatori. Per i motivi vedere Why can't you do bitwise operations on pointer in C, and is there a way around this?

Pertanto, per eseguire operazioni bit a bit sui puntatori, è necessario eseguire il cast dei puntatori per digitare unitpr_t e quindi eseguire operazioni bit a bit.

Ecco un esempio di una funzione che ho appena scritto per eseguire l'esclusione bitwise o di 2 puntatori da archiviare in una lista collegata XOR in modo da poter attraversare in entrambe le direzioni come una lista doppiamente collegata ma senza la penalità di memorizzazione 2 puntatori in ogni nodo.

template <typename T> 
T* xor_ptrs(T* t1, T* t2) 
{ 
    return reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(t1)^reinterpret_cast<uintptr_t>(t2)); 
    } 
+0

oltre all'aritmetica dei bit è anche bello se si desidera avere una semantica basata sugli indirizzi invece dei conteggi degli oggetti. – Alex

Problemi correlati