Recientemente me encontré con esta directiva de preprocesador #pragma pack(1) y me preguntaba por qué se usa.
Busqué en Google el uso y descubrí que tiene otras opciones, como empujar, hacer estallar, etc. ¿Alguien ha usado esto en su aplicación integrada?
Me gustaría saber algunos ejemplos de cómo/por qué ha utilizado esta directiva y en qué tipo de procesador. ¿Cuáles son las ventajas y desventajas de usar esta directiva?
Gracias.
#pragma pack(1)
asegura que los struct
elementos C se empaqueten en orden y en límites de bytes. Puede ahorrar RAM, que a menudo es valiosa en un microcontrolador.
Las estructuras empaquetadas también permiten la transmisión directamente sobre los búferes de memoria para el intercambio de datos:
void f(void *buf)
{
struct ip_header *hdr = (struct ip_header *)buf;
hdr->dst = 0x8000001;
}
Tenga cuidado donde usa #pragma pack
. Tiene un alcance global (ya que está en el preprocesador), por lo que olvidar apagarlo afectará a todos los #include
archivos. Si solo quiere empaquetar ciertas estructuras, considere usar GCC __attribute__ ((packed))
.
Sin embargo, debido a problemas de alineación, las estructuras empaquetadas pueden afectar el rendimiento. Por ejemplo:
Cuando se empaqueta en bytes:
struct
{
uint8_t a;
uint32_t b;
uint8_t c;
uint8_t d:
};
Se almacenará como (sin tener en cuenta el endianismo):
a, b0, b1, b2, b3, c, d
Sin embargo, muchas arquitecturas requieren que los accesos de 32 bits estén alineados con las direcciones de 32 bits. Con la estructura empaquetada, la máquina tendrá que hacer varios accesos de bytes y luego unirlos nuevamente.
Ante lo anterior struct
sin el empaquetado habilitado, el compilador podría reorganizarlo como:
b0, b1, b2, b3, un, c, re
Otra razón para empaquetar estructuras en límites de bytes es garantizar la alineación de los miembros al transferir datos entre diferentes procesadores.
A menudo necesito transferir estructuras de datos entre una MCU y una aplicación de PC host. La PC empaquetará estructuras en límites de 32 bits a menos que se le indique que las empaquete en límites de 1 byte. Una MCU PIC24F empaquetará estructuras en límites de 16 bits a menos que se le indique que las empaquete en límites de 1 byte.
Al indicarles a ambos que empaqueten sus estructuras en límites de 1 byte, garantiza que los datos estén en el mismo lugar cuando se accede a ellos en cualquier extremo. Sin él, necesitaría rellenar las estructuras con bytes de reserva para que los miembros de datos se alinearan correctamente.
El uso tradicional en el que he visto que se usa es para leer información de archivos. Por ejemplo, puede definir una estructura cuyos miembros coincidan con los de un encabezado de archivo BMP y luego leer todo el encabezado en una operación de lectura rápida. Bien, entonces BMP podría no ser el mejor ejemplo (su encabezado no tiene problemas de alineación en los sistemas de 32 bits), pero entiende la idea. Supongo que esto es igual de útil en el mundo integrado.
EnojadoEE