Pregunta

Existen muchos inconvenientes al usar void * en C (memoria relacionada, tipo relacionado, eficiencia eficiente ...). A pesar de ellos, los usamos mucho por la flexibilidad que brindan.

Enumere las desventajas / inconvenientes usando void * (y la solución preferida en C, si es posible).

EDITAR: por favor ve a través del siguiente enlace: http: / /attractivechaos.wordpress.com/2008/10/02/using-void-in-generic-c-programming-may-be-inefficient/

¿Fue útil?

Solución

No hay problemas de eficiencia con los punteros nulos. Las únicas limitaciones con los punteros nulos son:

  • no puede desreferenciar el puntero nulo por razones obvias
  • sizeof (void) es ilegal
  • no puede realizar aritmética de puntero en punteros vacíos

Sin embargo, GCC supone que sizeof (void) es 1 y permite la aritmética de punteros en punteros vacíos - ver aquí

Otros consejos

No estoy de acuerdo con la premisa de la pregunta. Usamos void * en C porque es la única forma de obtener polimorfismo. Ejemplo: funciones de biblioteca qsort y bsearch. Solo hay un inconveniente, que es que el polimorfismo basado en el vacío * no es seguro: una vez que lanza un puntero al vacío *, no hay nada que le impida lanzar ese vacío * al tipo de puntero incorrecto Error. Mis alumnos cometen este error con frecuencia.

Puede haber un costo de eficiencia porque a veces es necesario asignar espacio de almacenamiento dinámico para usar una estructura de datos polimórfica.

Cualquiera que quiera ver las ventajas y desventajas en el uso de estructuras de datos polimórficas con void * debe obtener una copia del libro de Dave Hanson C Interfaces e implementaciones

Uh ... no estoy seguro de que haya tantos. Por supuesto, nunca debe usar void * cuando no tiene que hacerlo. Si hay un tipo bien definido que puede usar, hágalo.

En mi experiencia, void * es mejor para "anónimo" punteros (¡qué sorpresa!), como en el valor de retorno de malloc () , y cuando solo se trata de búferes opacos de bits. A menudo, desea abordar esos búferes en, p. el nivel de bytes, y luego usarías unsigned char * , por supuesto.

Simplemente usando aleatoriamente void * donde sea que necesite un puntero simplemente se rompería, un código maloliente y, por supuesto, se evitará.

La publicación vinculada a compara operaciones con punteros vacíos con operaciones con plantillas C ++, y concluye que las plantillas son más eficientes. Esto no es una sorpresa, y el código C ++ que he visto usa punteros nulos rara vez o nunca. En general, no ofrece ninguna ventaja sobre otras instalaciones de C ++, y puede ser un agujero enorme en el sistema de tipos.

Sin embargo, C no tiene plantillas de estilo C ++, y se necesitan punteros nulos para implementar la funcionalidad que debe ser independiente del tipo de datos.

Por lo tanto, cuando está escribiendo en C, y necesita genérico, los punteros nulos son los medios más eficientes para obtenerlo (ya que son los únicos medios). Cuando escribes en C ++, hay mejores formas de hacer casi cualquier cosa que los punteros vacíos puedan lograr, así que no los uses.

Su enlace dado, es parcialmente cierto. Especialmente, cuando no se trata de objetos (estructuras) o, en general, de tipos que aún no están asignados. El uso de tipos nativos como ints, dobles, etc. y punteros vacíos (por ejemplo, para un contenedor) es casi siempre un asunto repulsivo, porque tienes la opción de lanzar el int (para un doble, esto no funciona) a un puntero o debe asignar memoria adicional para el tipo de datos.

La primera opción es mala porque no es portátil, quizás no se permiten los 0 como valor y simplemente se siente mal. La segunda opción desperdicia memoria y de hecho es una desaceleración (masiva) debido a las asignaciones adicionales.

Pero en la mayoría de los casos no se trata de tipos nativos, sino de objetos, mejor dicho con punteros a objetos, que ya están asignados, al menos yo sí. Nunca necesité una tabla hash o un mapa para enteros o dobles. Y tener diferentes implementaciones de contenedores solo para la seguridad del tipo de punteros me parece incorrecto, porque cada implementación aumentará su tamaño binario. Entonces, si solo necesita un contenedor para almacenar sus punteros, no hay ralentización ni desperdicio de memoria al usar void-punteros.

Pero tenga en cuenta que esto se trataba de implementaciones de contenedores, como por cierto el artículo de blog que mencionó. En general, hay muchas cosas que no puede lograr sin usar punteros vacíos.

No sé, he encontrado que los punteros vacíos son bastante efectivos para acceder a diferentes niveles de abstracción (ABC). Como un medio para navegar clases interconectadas en diferentes niveles de abstracción. Es tan simple, es increíble. Al igual que la fórmula para e o la proporción áurea, debe haber un ocultismo que rinda culto al vacío * es tan genial :)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top