uniones estructuras enum ejemplos conjuntos clase c unions

estructuras - Ejemplos de unión en C



union de conjuntos c++ (8)

Aquí hay un pequeño que uso todos los días:

struct tagVARIANT { union { struct __tagVARIANT { VARTYPE vt; WORD wReserved1; WORD wReserved2; WORD wReserved3; union { LONG lVal; /* VT_I4 */ BYTE bVal; /* VT_UI1 */ SHORT iVal; /* VT_I2 */ FLOAT fltVal; /* VT_R4 */ DOUBLE dblVal; /* VT_R8 */ VARIANT_BOOL boolVal; /* VT_BOOL */ _VARIANT_BOOL bool; /* (obsolete) */ SCODE scode; /* VT_ERROR */ CY cyVal; /* VT_CY */ DATE date; /* VT_DATE */ BSTR bstrVal; /* VT_BSTR */ IUnknown * punkVal; /* VT_UNKNOWN */ IDispatch * pdispVal; /* VT_DISPATCH */ SAFEARRAY * parray; /* VT_ARRAY */ BYTE * pbVal; /* VT_BYREF|VT_UI1 */ SHORT * piVal; /* VT_BYREF|VT_I2 */ LONG * plVal; /* VT_BYREF|VT_I4 */ FLOAT * pfltVal; /* VT_BYREF|VT_R4 */ DOUBLE * pdblVal; /* VT_BYREF|VT_R8 */ VARIANT_BOOL *pboolVal; /* VT_BYREF|VT_BOOL */ SCODE * pscode; /* VT_BYREF|VT_ERROR */ CY * pcyVal; /* VT_BYREF|VT_CY */ DATE * pdate; /* VT_BYREF|VT_DATE */ BSTR * pbstrVal; /* VT_BYREF|VT_BSTR */ IUnknown ** ppunkVal; /* VT_BYREF|VT_UNKNOWN */ IDispatch ** ppdispVal; /* VT_BYREF|VT_DISPATCH */ SAFEARRAY ** pparray; /* VT_BYREF|VT_ARRAY */ VARIANT * pvarVal; /* VT_BYREF|VT_VARIANT */ PVOID byref; /* Generic ByRef */ CHAR cVal; /* VT_I1 */ USHORT uiVal; /* VT_UI2 */ ULONG ulVal; /* VT_UI4 */ INT intVal; /* VT_INT */ UINT uintVal; /* VT_UINT */ DECIMAL * pdecVal; /* VT_BYREF|VT_DECIMAL */ CHAR * pcVal; /* VT_BYREF|VT_I1 */ USHORT * puiVal; /* VT_BYREF|VT_UI2 */ ULONG * pulVal; /* VT_BYREF|VT_UI4 */ INT * pintVal; /* VT_BYREF|VT_INT */ UINT * puintVal; /* VT_BYREF|VT_UINT */ } __VARIANT_NAME_3; } __VARIANT_NAME_2; DECIMAL decVal; } __VARIANT_NAME_1; };

Esta es la definición del tipo de datos de variante de automatización OLE. Como puede ver, tiene muchos tipos posibles. Existen muchas reglas sobre los tipos que puede usar en diferentes situaciones, dependiendo de las capacidades de su código de cliente deseado. No todos los tipos son compatibles con todos los idiomas.

Los tipos con VT_BYREF después de ellos son utilizados por lenguajes como VBScript que pasan los parámetros por referencia de forma predeterminada. Esto significa que si tiene algún código que se preocupe por los detalles de la estructura variante (como C ++) que son invocados por un código que no lo hace (como VB), entonces debe desreferenciar cuidadosamente el parámetro de la variante si es necesario.

Los tipos byref también se usan para devolver valores de funciones. También hay soporte para los tipos de matriz que utilizan el tipo de SAFEARRAY extrañamente mal SAFEARRAY , tan difícil de usar desde C ++.

Si tiene una matriz de cadenas, puede pasarla a vbscript, pero no puede usarse (excepto para imprimir el tamaño). Para leer realmente los valores, los datos de la matriz deben ser del tipo VT_BYREF | VT_BSTR VT_BYREF | VT_BSTR .

Estoy buscando algunos ejemplos de unión, no para entender cómo funciona la unión, con suerte lo hago, sino para ver qué tipo de hackeo hacen las personas con la unión.

Así que siéntete libre de compartir tu hack de unión (con alguna explicación, por supuesto :))


Casualmente, acabo de utilizar uno en una respuesta de here para poder tratar una palabra compuesta de campos de 6 bits como dos enteros sin signo de 16 bits.

Hace años, también usé uno para (el primer) compilador ARM C: las instrucciones en esos días eran todas de 32 bits, pero tenían diferentes diseños dependiendo de la instrucción exacta. Así que tuve una unión para representar una instrucción ARM, que contenía un conjunto de estructuras que cada una tenía los campos de bits apropiados para un tipo de instrucción específico.


Evite los "hacks" con la unión, causan dolores de cabeza a la portabilidad (endianness, problemas de alineación).

  • Un uso legítimo de unión es almacenar diferentes tipos de datos en el mismo lugar, preferiblemente con una etiqueta para que sepa de qué tipo es. Vea el ejemplo por 1800 INFORMACIÓN.

  • No utilice la unión para convertir entre tipos de datos, por ejemplo, de un número entero a varios bytes. Utilice el cambio y el enmascaramiento en lugar de la portabilidad.


Los sindicatos también se utilizan comúnmente en el análisis léxico y la etapa de análisis de procesadores de lenguaje, como compiladores e intérpretes. Aquí hay uno que estoy editando en este momento.

union { char c; int i; string *s; double d; Expression *e; ExpressionList *el; fpos_t fp; }

La unión se usa para asociar los valores semánticos con los símbolos del analizador léxico y las producciones del analizador sintáctico. Esta práctica es bastante común en los generadores de gramática, como yacc , que proporciona un apoyo explícito para ello. La unión puede contener cualquiera de sus valores, pero solo uno de ellos en ese momento. Por ejemplo, en cualquier punto del archivo de entrada, usted ha leído una constante de caracteres (almacenada en c ), o un número entero (almacenado en i ) o un número de coma flotante (almacenado en d ). El generador de gramática proporciona una asistencia considerable para determinar cuál de los valores se almacena en cualquier momento dependiendo de la regla que se está procesando.


Un clásico es representar un valor de tipo "desconocido", como en el núcleo de una máquina virtual simplista:

typedef enum { INTEGER, STRING, REAL, POINTER } Type; typedef struct { Type type; union { int integer; char *string; float real; void *pointer; } x; } Value;

Al usar esto, puede escribir código que maneje "valores" sin conocer su tipo exacto, por ejemplo, implementar una pila, etc.

Como esto está en (antiguo, anterior a C11) C, a la unión interna se le debe dar un nombre de campo en la struct externa. En C ++ puedes dejar que la union sea ​​anónima. Escoger este nombre puede ser difícil. Tiendo a ir con algo de una sola letra, ya que casi nunca se hace referencia de forma aislada y, por lo tanto, siempre está claro, desde el contexto, lo que está sucediendo.

El código para establecer un valor en un entero podría verse así:

Value value_new_integer(int v) { Value v; v.type = INTEGER; v.x.integer = v; return v; }

Aquí uso el hecho de que struct s puede devolverse directamente y tratarse casi como valores de un tipo primitivo (puede asignar struct s).


Usamos uniones para mensajes empaquetados en el trabajo (C / C ++), de modo que podemos pasar una estructura con una unión como un miembro de datos, y luego acceder a la ruta correcta en función del campo de identificación en la estructura.

Funcionó bien hasta que alguien escribió la estructura en un archivo, ahora estamos limitados a la información más grande utilizada en el archivo, porque a pesar de que hay una versión de archivo, nadie la cambió ...

Por lo tanto, aunque es útil para el trabajo en memoria, evite escribirlos a ciegas en el disco o la red.


#define DWORD unsigned int #define WORD unsigned short #define BYTE unsigned char typedef union _DWORD_PART_ { DWORD dwWord; struct { WORD dwMSB; WORD dwLSB; }hw; struct { BYTE byMSB; BYTE byMSBL; BYTE byLSBH; BYTE byLSB; } b; } DWORD_PART;

Esta es una manera fácil de acceder a las partes de las palabras. (Una vez que haya terminado, cualquier cambio en la endianidad de la plataforma también se puede manejar fácilmente)


struct InputEvent { enum EventType { EventKeyPressed, EventKeyPressRepeated, EventKeyReleased, EventMousePressed, EventMouseMoved, EventMouseReleased } Type; union { unsigned int KeyCode; struct { int x; int y; unsigned int ButtonCode; }; }; }; ... std::vector<InputEvent> InputQueue;

con el truco sindical puedo simplemente hacer un vector de objetos. Estoy seguro de que esto podría hacerse más limpio ... pero funciona para mí - KISS