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