¿Por qué las estructuras empaquetadas no forman parte del lenguaje C?

10

Cada compilador de C ofrece la opción de "empaquetar" estructuras de C (por ejemplo __attribute__ ((__packed__)), o #pragma pack()). Ahora, todos sabemos que se requiere empacar, si queremos enviar o almacenar datos de manera confiable. Esto también debe haber sido un requisito desde los primeros días del lenguaje C.

Entonces, ¿por qué las estructuras empaquetadas no son parte de la especificación del lenguaje C? ¿Ni siquiera están en C99 o C11 a pesar de que la necesidad de tenerlos se conoce desde hace décadas? ¿Qué me estoy perdiendo? ¿Por qué es específico del compilador?

grasbueschel
fuente
2
No son necesarios para escribir código C puro.
user253751

Respuestas:

7

Supongo que es porque depende de la combinación de CPU / compilador objetivo utilizado. Esto significa que es mejor ser una directiva compiladora (ya que está relacionada con eso) que un aspecto del lenguaje, porque ¿cómo especificar eso? La única forma en que podrían hacerlo es con la unión.

El artículo de Raymond da una idea de por qué esto es: http://www.catb.org/esr/structure-packing/

Frans Bouma
fuente
Artículo muy interesante (+1)
Giorgio
¿Qué dificultad habría para permitir que el código diga "Necesito una estructura que contenga 12 bytes; el campo X debe comportarse como un entero de 32 bits almacenado como little-endian de cuatro octetos en el desplazamiento 0; el campo Y debe comportarse como un entero de 64 bits almacenado como octetos bytes little-endian en el desplazamiento 4 "? El código para manejar eso en cualquier plataforma no debería ser peor que el tipo de cosas que los compiladores ya tienen que hacer para los campos de bits, y en los casos en que el programador especifique una alineación que coincida con la máquina nativa podría ser mucho más eficiente. En otras máquinas, sería menos eficiente pero aún portátil.
supercat
5

Hay tres factores principales.

  1. Algunos procesadores no pueden acceder a datos no alineados (por ejemplo, un número entero o flotante que comienza en una dirección impar). Intentar hacerlo desencadena una excepción.
  2. Algunos procesadores pueden acceder a datos no alineados, pero a un costo de rendimiento.
  3. Se accede a la mayoría de las estructuras mediante un único conjunto de código fuente C / C ++, y la interoperabilidad con otros lenguajes es la excepción, no la regla.

Con estos factores en mente, tanto los compiladores estándar como todos los compiladores C / C ++ rellenan rutinariamente las estructuras para garantizar una alineación óptima para el procesador, pero también proporcionan mecanismos para anular esto si es necesario con fines de interoperabilidad.

Esto de ninguna manera es algo que se haya pasado por alto. Se entiende muy bien y la situación actual es por diseño. Las últimas versiones del estándar C ++ tienen un amplio soporte para manejar los problemas de alineación, que quizás no conozca.

david.pfx
fuente
Cualquier argumento que pueda hacerse contra estructuras empaquetadas también podría usarse para justificar que los campos de bits sean una característica opcional. El acceso a los miembros de estructuras empaquetadas sería lento en algunos procesadores, rápido en otros, pero hacer que los compiladores intenten reemplazar las soluciones alternativas de código de usuario por la falta de funciones de acceso no alineado con un código más eficiente es mucho más complicado que simplemente tener compiladores que los programadores especifiquen qué necesitan.
supercat
@supercat: ¿por qué estás argumentando (o en contra)? No lo entiendo
david.pfx
Soy de la opinión de que los campos de bits deberían ser opcionales, pero si los campos de bits serán una característica obligatoria, entonces tendría sentido extenderlos de una manera que permita un control explícito del diseño de la estructura. De lo contrario, el efecto neto es que los compiladores tienen que hacer el 90% del trabajo que sería necesario para el control total del diseño, pero los programadores solo obtienen el 10% del beneficio.
supercat
@supercat: los campos de bits son enteros y siguen las mismas reglas de ordenación de diseño de bits que los enteros: implementación definida. Los miembros de la estructura se ordenan en los límites de caracteres según lo declarado, posiblemente con el empaque insertado. Conceptualmente están bastante separados. [Tendrá que hacer otra pregunta si desea ampliar su propuesta, pero no creo que funcione en absoluto.]
david.pfx
0

Es específico del compilador porque no está en el estándar. Y no está en el estándar porque sería difícil de especificar de una manera que no requeriría mucho esfuerzo de implementación para compiladores de plataformas oscuras con restricciones de alineación forzadas.

Y ninguno de esos esfuerzos tiene mucha justificación, porque cada compilador / plataforma que le importa a cualquiera que use un compilador C89 o posterior ya lo ha implementado.

soru
fuente
2
??? Respondió a la pregunta "¿Por qué no está en el idioma estándar" al decir "porque no está en el estándar" ...
Emilio Garavaglia
Eso fue lo que pensé primero, pero de nuevo, uno podría especificar la característica como "si la estructura se define con la palabra clave 'empaquetada', su tamaño se garantiza que será el mismo que el tamaño agregado de cada miembro individual. En plataformas que no admiten acceso de memoria no alineado, el acceso a uno de los valores de miembros de estructura es un comportamiento indefinido ". Esto permitiría a los desarrolladores en plataformas sin acceso no alineado conocer al menos el tamaño de las estructuras y el desplazamiento de cada miembro individual ...
grasbueschel
1
Sería posible hacer el trabajo de acceso no alineado en sistemas que no lo soportan en el hardware mediante la implementación de este tipo de estructuras como una matriz de bytes y la realización de las de desplazamiento de bits necesarios y &/ |operaciones de lectura / escritura de los valores de cada campo.
dan04
1
@ dan04: en muchos procesadores, un compilador podría generar código para acceso no alineado que fuera más eficiente que usar una secuencia de lecturas y cambios de bytes. Tener una sintaxis para eso facilitaría que dichos compiladores generen código eficiente que exigirles que reconozcan todas las diferentes formas en que los programadores podrían intentar escribir código para ensamblar bytes en tipos más largos.
supercat