Utilisation des unions en C pour un compactage et décompactage efficaces des données
Utilisation des unions en C pour un compactage et décompactage efficaces des données
Les unions offrent un moyen puissant et économe en mémoire de réinterpréter les mêmes octets comme différents types de données. Bien qu'initialement conçues pour la mémoire partagée entre variables mutuellement exclusives, les programmeurs C modernes utilisent souvent les unions pour le compactage, le décompactage et le type punning — particulièrement lors de la gestion de protocoles séries ou de communications bas niveau.
Comment une union partage la mémoire
Tous les membres d'une union partagent la même région de mémoire. Le plus grand membre détermine la taille de l'union, et chaque membre commence à la même adresse.
union { uint16_t word; struct { uint8_t byte1; uint8_t byte2; }; } u1;
Ici, word occupe deux octets, tandis que la structure imbriquée divise ces deux octets en byte1 et byte2. La disposition peut être visualisée comme suit :

Compactage de deux octets en un mot de 16 bits
Pour combiner deux valeurs 8 bits x et y en un mot de 16 bits, assignez-les aux membres de la structure, puis lisez le membre word :
u1.byte1 = y; u1.byte2 = x; uint16_t packed = u1.word;
Ce « type punning » est simple mais dépend de l'ordre des octets du processeur.
L'endianness du processeur est importante
Les systèmes little-endian stockent l'octet de poids faible en premier, tandis que les systèmes big-endian stockent l'octet de poids fort en premier. Considérons la séquence 0x01020304 :

L'exécution d'un test simple sur une machine little-endian donne :
#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; }
Sortie : Word is: 0X4321 — confirmant le stockage little-endian. Sur une cible big-endian, le même code produirait 0X2143.
Alternative bit à bit : compactage indépendant de l'endianness
Le décalage et le masque offrent un moyen portable de construire une valeur de 16 bits :
uint16_t word2 = (((uint16_t)byte3) << 8) | ((uint16_t)byte4);
Comparaison des deux méthodes :
#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; }
Sur un processeur big-endian : Word1 is: 0X2143, Word2 is: 0X2143. Sur un processeur little-endian : Word1 is: 0X4321, Word2 is: 0X2143. L'approche bit à bit garantit des résultats cohérents entre architectures.
Exemple pratique : envoi d'un float par UART
Les liaisons série transmettent généralement un octet à la fois. Pour envoyer un float 32 bits, nous pouvons utiliser une union pour visualiser le float comme un tableau de quatre octets :
union buffer { float f; struct { uint8_t byte[4]; }; };
Côté émission :
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);
Sortie : The received data is: 5.500000. L'union sépare proprement la représentation en octets de la valeur à virgule flottante, rendant le code lisible et maintenable.

Points clés
- Les unions permettent le type punning, mais les résultats dépendent de l'endianness.
- Les opérateurs bit à bit offrent un compactage portable, indépendant de l'architecture.
- Pour la clarté et la maintenance, de nombreux développeurs privilégient encore les unions dans les contextes embarqués.
- Les unions brillent lors de la transmission de structures de données arbitraires sur des liaisons orientées octets.
Pour explorer davantage le C, les unions et les systèmes embarqués, consultez ma liste complète d'articles.
Embarqué
- Sémaphores dans Nucleus RTOS : Services utilitaires et structures de données
- L'armée américaine fait progresser la maintenance conditionnelle avec capteurs innovants et analytique prédictive
- Comment l'IIoT et l'analytique transforment l'EHS : booster sécurité, efficacité et économies
- Construire une IA responsable et de confiance : guide pour l'explicabilité, la responsabilité et l'éthique
- Le Fog Computing Expliqué : Transformer le Flux de Données IoT et Réduire la Charge Cloud
- Les unions en C : Gestion mémoire efficace pour types multiples
- Visibilité de la chaîne d'approvisionnement : le rôle crucial des données et du contexte
- Révolutionner la gestion de flotte : intégration IA & IoT pour des opérations plus intelligentes
- IAoT industriel : fusion de l'IA et de l'IoT pour piloter l'innovation Industrie 4.0