Recherche…


Remarques

Les syndicats sont des outils très utiles, mais apportent quelques précautions importantes:

  • Il s'agit d'un comportement indéfini, conformément à la norme C ++, pour accéder à un élément d'une union qui n'était pas le dernier membre modifié. Bien que de nombreux compilateurs C ++ autorisent cet accès de manière bien définie, il s’agit d’extensions et ne peuvent être garanties sur tous les compilateurs.

    Une std::variant (depuis C ++ 17) est comme une union, mais elle vous indique seulement ce qu’elle contient actuellement (une partie de son état visible est le type de la valeur qu’elle contient à un moment donné: elle applique uniquement l’accès à la valeur). à ce type).

  • Les implémentations n'alignent pas nécessairement les membres de tailles différentes sur la même adresse.

Fonctions de base de l'Union

Les unions sont une structure spécialisée dans laquelle tous les membres occupent une mémoire qui se chevauchent.

union U {
    int a;
    short b;
    float c;
};
U u;

//Address of a and b will be equal
(void*)&u.a == (void*)&u.b;
(void*)&u.a == (void*)&u.c;

//Assigning to any union member changes the shared memory of all members
u.c = 4.f;
u.a = 5;
u.c != 4.f;

Utilisation typique

Les unions sont utiles pour minimiser l'utilisation de la mémoire pour les données exclusives, par exemple lors de l'implémentation de types de données mixtes.

struct AnyType {
    enum {
        IS_INT,
        IS_FLOAT
    } type;
    
    union Data {
        int as_int;
        float as_float;
    } value;

    AnyType(int i) : type(IS_INT) { value.as_int = i; }
    AnyType(float f) : type(IS_FLOAT) { value.as_float = f; }

    int get_int() const {
        if(type == IS_INT)
            return value.as_int;
        else
            return (int)value.as_float;
    }
    
    float get_float() const {
        if(type == IS_FLOAT)
            return value.as_float;
        else
            return (float)value.as_int;
    }
};

Comportement non défini

union U {
    int a;
    short b;
    float c;
};
U u;

u.a = 10;
if (u.b == 10) {
   // this is undefined behavior since 'a' was the last member to be
   // written to. A lot of compilers will allow this and might issue a
   // warning, but the result will be "as expected"; this is a compiler
   // extension and cannot be guaranteed across compilers (i.e. this is
   // not compliant/portable code).
}


Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow