Union declaration
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
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
|