Namespaces
Variants

Union declaration

From cppreference.net

Une union est un type constitué d'une séquence de membres dont le stockage se chevauche (par opposition à struct, qui est un type constitué d'une séquence de membres dont le stockage est alloué dans une séquence ordonnée). La valeur d'au plus un des membres peut être stockée dans une union à un moment donné.

Le spécificateur de type pour une union est identique au struct spécificateur de type sauf pour le mot-clé utilisé :

Table des matières

Syntaxe

union attr-spec-seq  (optionnel) nom  (optionnel) { struct-declaration-list } (1)
union attr-spec-seq  (optionnel) nom (2)
name - le nom de l'union en cours de définition
struct-declaration-list - un nombre quelconque de déclarations de variables, déclarations de champs de bits et déclarations d'assertions statiques. Les membres de type incomplet et les membres de type fonction ne sont pas autorisés.
attr-spec-seq - (C23) liste facultative d' attributs , appliqués au type union, non autorisée pour (2) si cette forme n'est pas suivie d'un ; (c'est-à-dire pas une déclaration anticipée).

Explication

L'union est seulement aussi grande que nécessaire pour contenir son plus grand membre (un remplissage de fin non nommé supplémentaire peut également être ajouté). Les autres membres sont alloués dans les mêmes octets dans le cadre de ce plus grand membre.

Un pointeur vers une union peut être converti en un pointeur vers chacun de ses membres (si une union a des membres de champ de bits, le pointeur vers l'union peut être converti en pointeur vers le type sous-jacent du champ de bits). De même, un pointeur vers n'importe quel membre d'une union peut être converti en un pointeur vers l'union englobante.

Si le membre utilisé pour accéder au contenu d'une union n'est pas le même que le dernier membre utilisé pour stocker une valeur, la représentation objet de la valeur qui a été stockée est réinterprétée comme une représentation objet du nouveau type (ceci est connu sous le nom de type punning ). Si la taille du nouveau type est supérieure à la taille du dernier type écrit, le contenu des octets excédentaires n'est pas spécifié (et peut être une représentation piégée). Avant C99 TC3 (DR 283) ce comportement était indéfini, mais communément implémenté de cette manière.

(depuis C99)

Similaire à struct, un membre sans nom d'une union dont le type est une union sans nom est appelé union anonyme . Chaque membre d'une union anonyme est considéré comme un membre de la struct ou de l'union englobante, en conservant leur disposition d'union. Cela s'applique récursivement si la struct ou l'union englobante est également anonyme.

struct v
{
   union // anonymous union
   {
       struct { int i, j; }; // anonymous structure
       struct { long k, l; } w;
   };
   int m;
} v1;
v1.i = 2;   // valid
v1.k = 3;   // invalid: inner structure is not anonymous
v1.w.k = 5; // valid

Similaire à struct, le comportement du programme est indéfini si l'union est définie sans aucun membre nommé (y compris ceux obtenus via des structs ou unions imbriquées anonymes).

(depuis C11)

Mots-clés

union

Notes

Voir l'initialisation des structures pour les règles concernant l'initialisation des structures et des unions.

Exemple

#include <assert.h>
#include <stdint.h>
#include <stdio.h>
int main(void)
{
    union S
    {
        uint32_t u32;
        uint16_t u16[2];
        uint8_t  u8;
    } s = {0x12345678}; // s.u32 est maintenant le membre actif
    printf("L'union S a une taille de %zu et contient %x\n", sizeof s, s.u32);
    s.u16[0] = 0x0011;  // s.u16 est maintenant le membre actif
    // la lecture de s.u32 ou s.u8 réinterprète la représentation objet
//  printf("s.u8 vaut maintenant %x\n", s.u8); // non spécifié, typiquement 11 ou 00
//  printf("s.u32 vaut maintenant %x\n", s.u32); // non spécifié, typiquement 12340011 ou 00115678
    // les pointeurs vers tous les membres d'une union sont égaux entre eux et à l'union
    assert((uint8_t*)&s == &s.u8);
    // cette union a 3 octets de remplissage final
    union pad
    {
        char  c[5]; // occupe 5 octets
        float f;    // occupe 4 octets, impose un alignement de 4
    } p = { .f = 1.23 }; // la taille est 8 pour satisfaire l'alignement de float
    printf("taille de l'union de char[5] et float est %zu\n", sizeof p);
}

Sortie possible :

L'union S a une taille de 4 et contient 12345678
taille de l'union de char[5] et float est 8

Rapports de défauts

Les rapports de défauts modifiant le comportement suivants ont été appliqués rétroactivement aux normes C publiées antérieurement.

DR Appliqué à Comportement publié Comportement corrigé
DR 499 C11 les membres des structs/unions anonymes étaient considérés comme membres du struct/union englobant ils conservent leur disposition en mémoire

Références

  • Norme C23 (ISO/CEI 9899:2024) :
  • 6.7.2.1 Spécificateurs de structure et d'union (p: TBD)
  • Norme C17 (ISO/CEI 9899:2018) :
  • 6.7.2.1 Spécificateurs de structure et d'union (p: 81-84)
  • Norme C11 (ISO/IEC 9899:2011) :
  • 6.7.2.1 Spécificateurs de structure et d'union (p: 112-117)
  • Norme C99 (ISO/IEC 9899:1999) :
  • 6.7.2.1 Spécificateurs de structure et d'union (p: 101-104)
  • Norme C89/C90 (ISO/IEC 9899:1990) :
  • 3.5.2.1 Spécificateurs de structure et d'union

Voir aussi

Documentation C++ pour Déclaration d'union