Namespaces
Variants

Union declaration

From cppreference.net

Una unión es un tipo que consiste en una secuencia de miembros cuyo almacenamiento se superpone (a diferencia de struct, que es un tipo que consiste en una secuencia de miembros cuyo almacenamiento se asigna en una secuencia ordenada). El valor de como máximo uno de los miembros puede almacenarse en una unión en cualquier momento.

El especificador de tipo para una unión es idéntico al struct especificador de tipo excepto por la palabra clave utilizada:

Contenidos

Sintaxis

union attr-spec-seq  (opcional) name  (opcional) { struct-declaration-list } (1)
union attr-spec-seq  (opcional) name (2)
name - el nombre de la unión que se está definiendo
struct-declaration-list - cualquier número de declaraciones de variables, declaraciones de campos de bits y declaraciones static assert. No se permiten miembros de tipo incompleto ni miembros de tipo función.
attr-spec-seq - (C23) lista opcional de atributos , aplicados al tipo unión, no permitidos para (2) si dicha forma no va seguida de un ; (es decir, no es una declaración anticipada).

Explicación

La unión solo es tan grande como es necesario para contener su miembro más grande (también se puede agregar relleno adicional sin nombre al final). Los otros miembros se asignan en los mismos bytes como parte de ese miembro más grande.

Un puntero a una unión puede convertirse a un puntero a cada uno de sus miembros (si una unión tiene miembros de campo de bits, el puntero a la unión puede convertirse al puntero al tipo subyacente del campo de bits). Del mismo modo, un puntero a cualquier miembro de una unión puede convertirse a un puntero a la unión que lo contiene.

Si el miembro utilizado para acceder al contenido de una unión no es el mismo que el miembro utilizado por última vez para almacenar un valor, la representación del objeto del valor que fue almacenado se reinterpreta como una representación del objeto del nuevo tipo (esto se conoce como type punning ). Si el tamaño del nuevo tipo es mayor que el tamaño del tipo escrito por última vez, el contenido de los bytes excedentes no está especificado (y puede ser una representación trampa). Antes de C99 TC3 (DR 283) este comportamiento no estaba definido, pero comúnmente se implementaba de esta manera.

(desde C99)

Similar a struct, un miembro sin nombre de una union cuyo tipo es una union sin name se conoce como union anónima . Cada miembro de una union anónima se considera miembro de la struct o union contenedora manteniendo su diseño de union. Esto se aplica recursivamente si la struct o union contenedora también es anónima.

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

Similar a struct, el comportamiento del programa es indefinido si se define una union sin ningún miembro nombrado (incluyendo aquellos obtenidos mediante structs o unions anidadas anónimas).

(desde C11)

Palabras clave

union

Notas

Consulte inicialización de estructuras para conocer las reglas sobre la inicialización de estructuras y uniones.

Ejemplo

#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 es ahora el miembro activo
    printf("La unión S tiene tamaño %zu y contiene %x\n", sizeof s, s.u32);
    s.u16[0] = 0x0011;  // s.u16 es ahora el miembro activo
    // leer desde s.u32 o desde s.u8 reinterpreta la representación del objeto
//  printf("s.u8 es ahora %x\n", s.u8); // no especificado, típicamente 11 o 00
//  printf("s.u32 es ahora %x\n", s.u32); // no especificado, típicamente 12340011 o 00115678
    // los punteros a todos los miembros de una unión se comparan iguales a sí mismos y a la unión
    assert((uint8_t*)&s == &s.u8);
    // esta unión tiene 3 bytes de relleno final
    union pad
    {
        char  c[5]; // ocupa 5 bytes
        float f;    // ocupa 4 bytes, impone alineación 4
    } p = { .f = 1.23 }; // el tamaño es 8 para satisfacer la alineación de float
    printf("tamaño de la unión de char[5] y float es %zu\n", sizeof p);
}

Salida posible:

La unión S tiene tamaño 4 y contiene 12345678
tamaño de la unión de char[5] y float es 8

Informes de defectos

Los siguientes informes de defectos que modifican el comportamiento se aplicaron retroactivamente a los estándares de C publicados anteriormente.

DR Applied to Behavior as published Correct behavior
DR 499 C11 los miembros de structs/uniones anónimos se consideraban miembros del struct/unión contenedor conservan su diseño de memoria

Referencias

  • Estándar C23 (ISO/IEC 9899:2024):
  • 6.7.2.1 Especificadores de estructura y unión (p: TBD)
  • Estándar C17 (ISO/IEC 9899:2018):
  • 6.7.2.1 Especificadores de estructura y unión (p: 81-84)
  • Estándar C11 (ISO/IEC 9899:2011):
  • 6.7.2.1 Especificadores de estructura y unión (p: 112-117)
  • Estándar C99 (ISO/IEC 9899:1999):
  • 6.7.2.1 Especificadores de estructura y unión (p: 101-104)
  • Estándar C89/C90 (ISO/IEC 9899:1990):
  • 3.5.2.1 Especificadores de estructura y unión

Véase también

Documentación de C++ para Declaración de union