¿Es una buena idea usar intptr_t
como un almacenamiento de uso general (para contener punteros y valores enteros) en lugar de void*
? (Como se ve aquí: http://www.crystalspace3d.org/docs/online/manual/Api1_005f0-64_002dBit-Portability-Changes.html)
Por lo que ya he leído:
int
-> void*
-> int
no se garantiza que el viaje de ida y vuelta mantenga el valor original; supongo int
-> intptr_t
-> int
servirá
- aritmética de punteros en ambos
void*
y intptr_t
requieren lanzamientos, por lo que ninguno obtiene ventaja aquí
void*
significa moldes menos explícitos al almacenar punteros, intptr_t
significa menos conversiones al almacenar valores enteros
intptr_t
requiere C99
¿Qué más debo tener en cuenta?
¿Es una buena idea usar intptr_t
como un almacenamiento de uso general (para contener punteros y valores enteros) en lugar de void*
?
No.
intptr_t
no se garantiza que exista. Primero, como nota, se introdujo en C99. En segundo lugar, no se requiere que las implementaciones tengan un tipo entero lo suficientemente grande como para contener valores de puntero convertidos sin pérdida de información.
Convirtiendo un int
para intptr_t
y atrás está improbable perder información, pero no hay garantía real de que intptr_t
es más ancho que int
.
Si desea almacenar valores de puntero, guárdelos en objetos de puntero. Para eso están los objetos de puntero.
Cualquier puntero a un objeto o tipo incompleto se puede convertir en void*
y viceversa sin pérdida de información. No existe tal garantía para los punteros a funciones, pero cualquier tipo de puntero a función se puede convertir a cualquier otro tipo de puntero a función y viceversa sin pérdida de información. (Me refiero al estándar C; creo que POSIX ofrece algunas garantías adicionales).
Si desea almacenar un número entero o un valor de puntero en el mismo objeto, lo primero que debe hacer es repensar su diseño. Si ya lo hizo y llegó a la conclusión de que realmente desea hacerlo, considere usar una unión (y mantenga un registro cuidadoso de qué tipo de valor ha almacenado más recientemente).
Hay APIs que usan un void*
argumento para permitir que se pasen datos arbitrarios; ver, por ejemplo, el POSIX pthread_create()
función. Se puede abusar de esto emitiendo un valor entero a void*
pero es más seguro pasar el habla a de un objeto entero.
No, no se puede garantizar que un tipo en particular sea una forma razonable de almacenar tanto punteros como números enteros y, además, hace que el código sea confuso. Hay una mejor manera.
Si desea almacenar un número entero y un puntero en el mismo objeto, el método limpio y portátil es usar una unión:
union foo {
int integer_foo;
void *pointer_foo;
};
Esto es portátil y le permite almacenar ambos tipos de cosas en el tamaño de almacenamiento necesario para el más grande de los dos. Está garantizado que siempre funcionará.
No. (Si lo fuera, simplemente habrían agregado la semántica de intptr_t a
void*
)– Billy ONeal
29 de febrero de 2012 a las 2:34
La publicación pregunta “(para contener punteros y valores enteros)”, pero luego solo discute
int
,void *
yintptr_t
. Comouintmax_t
,size_t
,long long
etc. también son tipos enteros, parece que la pregunta es solo sobre punteros de objetos,intptr_t
yint
tipos– chux – Reincorporar a Monica
28 de enero de 2016 a las 23:11