Manufactura industrial
Internet industrial de las cosas | Materiales industriales | Mantenimiento y reparación de equipos | Programación industrial |
home  MfgRobots >> Manufactura industrial >  >> Industrial Internet of Things >> Incrustado

Uso de uniones en C para empaquetado y desempaquetado eficiente de datos

Uso de uniones en C para empaquetado y desempaquetado eficiente de datos

Las uniones proporcionan una forma potente y eficiente en memoria de reinterpretar los mismos bytes como diferentes tipos de datos. Aunque originalmente se diseñaron para memoria compartida entre variables mutuamente exclusivas, los programadores modernos de C a menudo usan uniones para empaquetado, desempaquetado y type punning —especialmente al manejar protocolos serie o comunicaciones de bajo nivel.

Cómo una unión comparte memoria

Todos los miembros de una unión comparten la misma región de memoria. El miembro más grande determina el tamaño de la unión, y cada miembro comienza en la misma dirección.

union { uint16_t word; struct { uint8_t byte1; uint8_t byte2; }; } u1;

Aquí, word ocupa dos bytes, mientras que la estructura anidada divide esos dos bytes en byte1 y byte2. La disposición puede visualizarse como:

Uso de uniones en C para empaquetado y desempaquetado eficiente de datos

Empaquetando dos bytes en una palabra de 16 bits

Para combinar dos valores de 8 bits x e y en una palabra de 16 bits, asígnelos a los miembros de la estructura y luego lea el miembro word:

u1.byte1 = y; u1.byte2 = x; uint16_t packed = u1.word;

Este "data punning" es directo pero depende del orden de bytes del procesador.

El endianness del procesador importa

Los sistemas little-endian almacenan el byte menos significativo primero, mientras que los big-endian almacenan el más significativo primero. Considere la secuencia 0x01020304:

Uso de uniones en C para empaquetado y desempaquetado eficiente de datos

Ejecutar una prueba simple en una máquina little-endian produce:

#include <stdio.h> #include <stdint.h> int main() { union { struct { uint8_t byte1; uint8_t byte2; }; uint16_t word; } u1; u1.byte1 = 0x21; u1.byte2 = 0x43; printf("Word is: %#X\n", u1.word); return 0; }

Salida: Word is: 0X4321 —confirmando almacenamiento little-endian. En un objetivo big-endian el mismo código produciría 0X2143.

Alternativa bitwise: empaquetado independiente del endianness

Los desplazamientos y máscaras proporcionan una forma portable de construir un valor de 16 bits:

uint16_t word2 = (((uint16_t)byte3) << 8) | ((uint16_t)byte4);

Comparando ambos métodos:

#include <stdio.h> #include <stdint.h> int main() { union { struct { uint8_t byte1; uint8_t byte2; }; uint16_t word1; } u1; u1.byte1 = 0x21; u1.byte2 = 0x43; printf("Word1 is: %#X\n", u1.word1); uint8_t byte3 = 0x21, byte4 = 0x43; uint16_t word2 = (((uint16_t)byte3) << 8) | ((uint16_t)byte4); printf("Word2 is: %#X\n", word2); return 0; }

En un procesador big-endian: Word1 is: 0X2143, Word2 is: 0X2143. En little-endian: Word1 is: 0X4321, Word2 is: 0X2143. El enfoque bitwise garantiza resultados consistentes entre arquitecturas.

Ejemplo práctico: Enviando un float por UART

Los enlaces serie típicamente transmiten un byte a la vez. Para enviar un float de 32 bits, podemos usar una unión para ver el float como un array de cuatro bytes:

union buffer { float f; struct { uint8_t byte[4]; }; };

Lado transmisor:

union buffer tx; union buffer rx; float f1 = 5.5f; tx.f = f1; for (int i = 0; i < 4; ++i) { // send tx.byte[i] over UART rx.byte[i] = tx.byte[i]; // Simulated receive } printf("The received data is: %f\n", rx.f); 

Salida: The received data is: 5.500000. La unión separa limpiamente la representación en bytes del valor de punto flotante, haciendo el código legible y mantenible.

Uso de uniones en C para empaquetado y desempaquetado eficiente de datos

Conclusiones clave

Para explorar más sobre C, uniones y sistemas embebidos, explore mi lista completa de artículos.

Incrustado

  1. El Ejército de EE. UU. Avanza en Mantenimiento Basado en Condición con Sensores Innovadores y Analítica Predictiva
  2. Litmus y Oden Lanzan Soluciones IIoT Integradas para Fabricación Inteligente
  3. Visibilidad de la cadena de suministro: el papel crucial de los datos y el contexto
  4. Revolucionando la Gestión de Flotas: Integración de IA e IoT para Operaciones Más Inteligentes
  5. Semaforos en Nucleus RTOS: Servicios de utilidad y estructuras de datos
  6. CyrusOne mejora experiencia de usuario con monitorización de aplicaciones en tiempo real
  7. Cómo IIoT y Analítica de Datos Transforman EHS: Impulsando Seguridad, Eficiencia y Ahorros
  8. Construyendo IA responsable y confiable: Guía para explicabilidad, rendición de cuentas y ética
  9. Computación en la Niebla Explicada: Transformando el Flujo de Datos IoT y Reduciendo la Carga en la Nube
  10. AIoT industrial: Fusionando IA e IoT para impulsar la innovación de Industria 4.0
  11. Uniones en C explicadas: Gestión eficiente de memoria para múltiples tipos de datos