¿Usando intptr_t en lugar de void*?

5 minutos de lectura

avatar de usuario
Gepard

¿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?

  • 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 * y intptr_t. Como uintmax_t, size_t, long longetc. también son tipos enteros, parece que la pregunta es solo sobre punteros de objetos, intptr_t y int tipos

    – chux – Reincorporar a Monica

    28 de enero de 2016 a las 23:11

avatar de usuario
keith thompson

¿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.

  • Por favor expanda en “improbable perder información”. intptr_t hace ida y vuelta un puntero a uno de los compara Igualmente – es ese patrón potencialmente diferente a la pérdida de información de su comentario.

    – chux – Reincorporar a Monica

    28/01/2016 a las 20:55

  • @chux: Como dije, no hay garantía de que intptr_t es más ancho que int (aunque no conozco ninguna implementación donde no lo esté). Si, por ejemplo, intptr_t es de 32 bits y int es de 64 bits, luego convertir un int para intptr_t y de vuelta a int podría perder información. Específicamente, si el int el valor está fuera del rango de intptr_tla primera conversión genera un resultado definido por la implementación.

    –Keith Thompson

    28 de enero de 2016 a las 22:54

  • Lo sentimos, leyó la respuesta incorrectamente como “Convertir un puntero para intptr_t y atrás es poco probable que pierda información…”. Mi comentario se basó en ese pensamiento. Estoy de acuerdo con la rareza de la int/intptr_t cuestiones.

    – chux – Reincorporar a Monica

    28 de enero de 2016 a las 23:04

avatar de usuario
Sidra de pera

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á.

  • Hacer int y void* tienen una subsecuencia inicial común en términos de diseño? De lo contrario, esto es no portátil, eres no permitido almacenar ambos miembros a la vez y esto es absolutamente no Garantizado para “siempre trabajar”.

    – Carreras de ligereza en órbita

    08/02/2014 a las 17:39

  • @LightnessRacesinOrbit No creo que esté afirmando que se pueden almacenar dos valores a la vez. “ambos” significa que un int puede almacenarse en él, y un void * puede almacenarse en él, pero no hay ninguna sugerencia de simultaneidad. NÓTESE BIEN. No importaría si int y void* tenía una secuencia inicial común ya que esa regla solo se aplica a las estructuras.

    –MM

    28/01/2016 a las 20:34

  • @MM: Creo que “ambos” implica simultaneidad de una manera que “cualquiera” no lo habría hecho, pero quién sabe. Ciertamente, el OP está buscando simultaneidad dado que se habla de conversiones de ida y vuelta en la pregunta, por lo que si esta respuesta no es incorrecta, al menos se publica en la pregunta incorrecta: P

    – Carreras de ligereza en órbita

    28 de enero de 2016 a las 22:03


¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad