Недостатки использования указателей void * в C - PullRequest
0 голосов
/ 04 декабря 2008

Есть много недостатков использования void * в C (связанных с памятью, типом, эффективностью ...). Несмотря на это, мы часто используем их для обеспечения гибкости, которую они обеспечивают.

Перечислите недостатки / недостатки, используя void * (и предпочтительное решение в C - если возможно).

EDIT: Пожалуйста, перейдите по следующей ссылке: http://attractivechaos.wordpress.com/2008/10/02/using-void-in-generic-c-programming-may-be-inefficient/

Ответы [ 6 ]

14 голосов
/ 04 декабря 2008

Я не согласен с предпосылкой вопроса. Мы используем void * в C, потому что это единственный способ получить полиморфизм. Пример: библиотечные функции qsort и bsearch. Есть только один недостаток, который заключается в том, что полиморфизм, основанный на void *, небезопасен: после того, как вы приведете указатель к void *, ничто не помешает вам привести этот void * к неправильному типу указателя по ошибке , Мои ученики часто делают эту ошибку.

Могут быть затраты на эффективность, поскольку иногда необходимо выделить пространство кучи для использования полиморфной структуры данных.

Любой, кто хочет увидеть преимущества и недостатки использования полиморфных структур данных с void *, должен получить копию книги Дэйва Хансона Интерфейсы и реализации

14 голосов
/ 04 декабря 2008

Нет проблем эффективности с указателями пустоты. Единственные ограничения с указателями void:

  • вы не можете разыменовать пустой указатель по очевидным причинам
  • sizeof(void) незаконно
  • вы не можете выполнять арифметику указателей для пустых указателей

Однако GCC предполагает, что sizeof(void) равен 1 и допускает арифметику указателей на пустых указателях - см. Здесь

3 голосов
/ 04 декабря 2008

Э-э ... Я не уверен, что их так много. Конечно, вы никогда не должны использовать void*, когда вам не нужно. Если есть четко определенный тип, который вы можете использовать, то сделайте это.

По моему опыту, void* лучше всего подходит для "анонимных" указателей (какой шок!), Как в возвращаемом значении malloc(), так и при работе только с непрозрачными буферами битов. Часто вы хотите обратиться к этим буферам, например, уровень байта, и тогда вы, конечно, будете использовать unsigned char *.

Просто случайное использование void*, где бы вам ни понадобился указатель, будет просто сломан, вонючий код, и его, конечно, следует избегать.

2 голосов
/ 04 декабря 2008

Связанный пост сравнивает операции с пустыми указателями с операциями с шаблонами C ++ и делает вывод, что шаблоны более эффективны. Это не удивительно, и код C ++, который я видел, использует пустые указатели редко или никогда. Как правило, он не дает никаких преимуществ перед другими средствами C ++ и может стать зияющей дырой в системе типов.

Однако в C нет шаблонов в стиле C ++, и указатели void необходимы для реализации функциональности, которая должна быть независимой от типа данных.

Поэтому, когда вы пишете на C, и вам нужна универсальность, указатели void являются наиболее эффективным средством его получения (поскольку они являются единственными средствами). Когда вы пишете на C ++, есть лучшие способы сделать почти все, что могут сделать указатели void, поэтому не используйте их.

1 голос
/ 21 февраля 2010

Не знаю, я обнаружил, что пустые указатели довольно эффективны для доступа к различным уровням абстракции (ABC). Как средство навигации связанных классов на разных уровнях абстракции. Это так просто, это круто. Как и формула е или золотое сечение, должен быть оккульт, который поклоняется пустоте * это так здорово :)

1 голос
/ 04 декабря 2008

Ваша ссылка частично верна. Особенно, когда вы не имеете дело с объектами (структурами) или вообще с типами, которые еще не выделены. Использование нативных типов, таких как int, double и т. Д. И void-указателей (например, для контейнера), почти всегда является непростым делом, потому что у вас есть выбор: привести int (для double это не работает) к указателю вам нужно выделить дополнительную память для типа данных.

Первый выбор плох, потому что он не переносимый, 0 могут быть недопустимы в качестве значения, и он просто чувствует себя плохо. Второй вариант тратит впустую память и действительно (сильно) замедляется из-за дополнительных выделений.

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

Но обратите внимание, это все о реализации контейнеров, как, например, в статье в блоге, которую вы упомянули. В общем, есть много вещей, которые вы не можете выполнить без использования указателей void.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...