¿Usando intptr t en lugar de void*?


¿Es una buena idea usar intptr_t como un almacenamiento de propósito 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 de ida y vuelta no está garantizada para mantener el valor original; supongo int -> intptr_t -> int hará
  • la aritmética de punteros tanto en void* como en intptr_t requiere moldes, así que ninguno obtiene ventaja aquí
  • void* significa menos casts explícitos cuando se almacenan punteros, intptr_t significa menos casts cuando se almacenan valores enteros
  • intptr_t requiere C99

¿Qué más debo tener en cuenta?

Author: RzR, 2012-02-29

2 answers

¿Es una buena idea usar intptr_t como un almacenamiento de propósito general (para contener punteros y valores enteros) en lugar de void*?

No.

intptr_t no se garantiza su existencia. Primero, como usted nota, fue introducido 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.

Convertir un int a intptr_t y volver es poco probable para perder información, pero hay ninguna garantía real de que intptr_t sea mayor que int.

Si desea almacenar valores de puntero, almacénelos en objetos de puntero. Para eso están los objetos puntero.

Cualquier puntero a un objeto o tipo incompleto se puede convertir a void* y viceversa sin pérdida de información. No hay tal garantía para los punteros a funciones but pero cualquier tipo de puntero a función se puede convertir a cualquier otro tipo de puntero a función y volver sin pérdida de información. (Me refiero a al estándar C; creo que POSIX proporciona algunas garantías adicionales.)

Si desea almacenar un valor entero o un puntero en el mismo objeto, lo primero que debe hacer es repensar su diseño. Si ya lo has hecho, y has llegado a la conclusión de que realmente quieres hacerlo, considera usar una unión (y mantener un seguimiento cuidadoso del tipo de valor que has almacenado más recientemente).

Hay APIs que usan un argumento void* para permitir que se pasen datos arbitrarios; vea, para ejemplo, el POSIX pthread_create() función. Se puede abusar de esto lanzando un valor entero a void* pero es más seguro pasar la dirección de un objeto entero.

 28
Author: Keith Thompson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-01-28 22:54:49

No, no se puede garantizar que cualquier tipo en particular sea una forma razonable de almacenar tanto punteros como enteros, y además, hace que su código sea confuso. Hay una manera mejor.

Si desea almacenar un entero y un puntero en el mismo objeto, el método clean and portable 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á.

 5
Author: Perry,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-01-28 20:27:59