Использование intptr_t вместо void *? - PullRequest
22 голосов
/ 29 февраля 2012

Является ли хорошей идеей использовать intptr_t в качестве хранилища общего назначения (для хранения указателей и целочисленных значений) вместо void*?(Как видно здесь: http://www.crystalspace3d.org/docs/online/manual/Api1_005f0-64_002dBit-Portability-Changes.html)

Для того, что я уже прочитал:

  • int -> void* -> int, туда и обратно не гарантируетсяисходное значение; я думаю, int -> intptr_t -> int выполнит
  • арифметику указателей на void* и intptr_t, требующие приведения, поэтому здесь никто не получает преимущества
  • void* означает менее явное приведение при хранении указателей, intptr_t означает меньшее приведение при сохранении целочисленных значений
  • intptr_t требует C99

Что еще следует учитывать?

Ответы [ 2 ]

29 голосов
/ 29 февраля 2012

Целесообразно ли использовать intptr_t в качестве хранилища общего назначения (для хранения указателей и целочисленных значений) вместо void*?

Нет.

intptr_t не гарантируется.Во-первых, как вы заметили, он был представлен в C99.Во-вторых, реализациям не требуется иметь достаточно большой целочисленный тип для хранения преобразованных значений указателя без потери информации.

Преобразование int в intptr_t и обратно маловероятно потерятьинформация, но нет реальной гарантии, что intptr_t шире, чем int.

Если вы хотите сохранить значения указателя, сохраните их в объектах указателя.Для этого и нужны объекты-указатели.

Любой указатель на объект или неполный тип может быть преобразован в void* и обратно без потери информации.Нет такой гарантии для указателей на функции - но любой тип указатель на функцию может быть преобразован в любой другой тип указатель на функцию и обратно без потери информации.(Я имею в виду стандарт C; я думаю, что POSIX предоставляет некоторые дополнительные гарантии.)

Если вы хотите сохранить целое число или значение указателя в том же объекте, первое, что вы должны сделать, это повторнопродумайте свой дизайн.Если вы уже сделали это и пришли к выводу, что действительно хотите это сделать, рассмотрите возможность использования объединения (и внимательно следите за тем, какое значение вы сохранили в последнее время).

Существуют APIкоторые используют аргумент void*, чтобы разрешить передачу произвольных данных;см., например, функцию POSIX pthread_create().Это может быть использовано путем приведения целочисленного значения к void*, но безопаснее передать адрес целочисленного объекта.

5 голосов
/ 29 февраля 2012

Нет, вы не можете быть уверены, что какой-то конкретный тип является разумным способом хранения как указателей, так и целых чисел, и, кроме того, это делает ваш код запутанным. Есть лучший способ.

Если вы хотите сохранить целое число и указатель в одном и том же объекте, чистый и переносимый метод - использовать объединение:

union foo {
   int integer_foo;
   void *pointer_foo;
}

Это портативное устройство, позволяющее хранить оба вида вещей в том объеме, который необходим для большего из двух. Это гарантированно всегда работает.

...