2009-12-04 21 views
169

¿Qué es uintptr_t y para qué se puede usar?¿Qué es uintptr_t tipo de datos

+5

Detalles adicionales de este tipo, así como otros tipos relacionados se pueden encontrar aquí: http://www.opengroup.org/onlinepubs/000095399/basedefs/stdint.h.html – Void

+0

http: //en.cppreference .com/w/cpp/types/integer listas 'std :: uintptr_t' y' std :: intptr_t' a C++ 11 opcional. – alfC

Respuesta

127

Es un int sin signo que es capaz de almacenar un puntero. Lo que generalmente significa que es del mismo tamaño que un puntero.

Opcionalmente se define en C++ 11 y estándares posteriores.

Una razón común para querer un tipo entero que pueda contener el tipo de puntero de una arquitectura es realizar operaciones de entero en un puntero u ocultar el tipo de un puntero proporcionándolo como un "identificador" entero.

Editar: Tenga en cuenta que Steve Jessop tiene algunos detalles adicionales muy interesantes (que no voy a robar) in another answer here para usted tipos pedantes :)

+40

Tenga en cuenta que 'size_t' solo necesita ser suficiente para contener el tamaño del objeto más grande y puede ser más pequeño que un puntero. Esto se esperaría en arquitecturas segmentadas como 8086 (16 bits 'size_t', pero 32 bits' void * ') – MSalters

+2

para representar la diferencia entre dos punteros, tiene' ptrdiff_t'. 'uintptr_t' no es para eso. – jalf

+3

@jalf: Para la diferencia, sí, pero para * distance *, querrías un tipo sin firmar. –

16

Es un entero sin signo exactamente con el tipo del tamaño de un puntero. Siempre que necesite hacer algo inusual con un puntero, como por ejemplo invertir todos los bits (no pregunte por qué), lo transfiere al uintptr_t y lo manipula como un número entero normal, luego lo rechaza.

+5

Por supuesto que podrías hacer eso, pero eso sería un comportamiento indefinido. Creo que lo único que puedes hacer con el resultado del lanzamiento de uintptr_t es pasarlo sin cambios y devolverlo, todo lo demás es UB. – sleske

+0

Hay momentos en los que necesita jugar con los bits, y normalmente generaría errores de compilación. Un ejemplo común es la aplicación de la memoria alineada de 16 bytes para ciertas aplicaciones críticas de video y rendimiento. http://stackoverflow.com/questions/227897/solve-the-memory-alignment-inc-c-interview-question-that-stumped-me – DevNull

+3

@sleske eso no es cierto. En máquinas que tienen tipos autoalineados, los dos bits menos significativos de un puntero van a ser cero (porque las direcciones son múltiplos de 4 u 8). He visto programas que explotan esto para comprimir datos. – saadtaame

183

En primer lugar, cuando se formuló la pregunta, uintptr_t no estaba en C++. Está en C99, en <stdint.h>, como un tipo opcional. Muchos compiladores C++ 03 proporcionan ese archivo. También está en C++ 11, en <cstdint>, donde nuevamente es opcional, y que se refiere a C99 para la definición.

En C99, se define como "un tipo de entero sin signo con la propiedad de que cualquier apuntador válido a void se puede convertir a este tipo, luego convertido de nuevo a puntero a void, y el resultado se comparará con el puntero original ".

Toma esto para decir lo que dice. No dice nada sobre el tamaño.

uintptr_t podría ser del mismo tamaño que void*. Puede ser más grande. Es concebible que sea más pequeño, aunque una implementación de C++ se aproxima perversa. Por ejemplo, en una plataforma hipotética donde void* es de 32 bits, pero solo se utilizan 24 bits de espacio de direcciones virtuales, puede tener un uintptr_t de 24 bits que cumpla con los requisitos. No sé por qué una implementación haría eso, pero el estándar lo permite.

+4

Gracias por el "". Mi aplicación no se compiló debido a la declaración uintptr_t. Pero cuando leo tu comentario agrego "#include " y ahora sí funciona. ¡Gracias! – JavaRunner

+1

¿Por qué alguien querría lanzar un puntero a int? –

+2

Para [asignar memoria alineada] (http://stackoverflow.com/q/227897/183120), entre otros usos, por ejemplo? – legends2k

6

Ya hay muchas buenas respuestas para la parte "qué es el tipo de datos uintptr_t". Trataré de abordar el "¿para qué se puede usar?" parte en esta publicación.

Principalmente para operaciones bit a bit en punteros. Recuerde que en C++ uno no puede realizar operaciones bit a bit en punteros. Por razones, consulte Why can't you do bitwise operations on pointer in C, and is there a way around this?

Por lo tanto, para realizar operaciones a nivel de bit en punteros, se necesitarán punteros para escribir unitpr_t y luego realizar operaciones bit a bit.

Aquí hay un ejemplo de una función que acabo de escribir para hacer bitwise exclusive o de 2 punteros para almacenar en una lista XOR vinculada para que podamos atravesar en ambas direcciones como una lista doblemente enlazada pero sin la penalidad de almacenar 2 punteros en cada 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

que no sea bit aritmético, también es bueno si desea tener una semántica basada en direcciones en lugar de recuentos de objetos. – Alex