Недостатки использования указателей void* в C

StackOverflow https://stackoverflow.com/questions/339880

  •  19-08-2019
  •  | 
  •  

Вопрос

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

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

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

Это было полезно?

Решение

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

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

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

Другие советы

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top