代码之家  ›  专栏  ›  技术社区  ›  claf

C中的并集示例[已关闭]

  •  32
  • claf  · 技术社区  · 16 年前

    因此,请随意分享您的工会黑客(当然有一些解释:)

    8 回复  |  直到 12 年前
        1
  •  42
  •   unwind    9 年前

    一个经典是表示“未知”类型的值,如在过于简单的虚拟机的核心中:

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

    使用它,您可以编写处理“值”的代码,而不知道它们的确切类型,例如实现堆栈等等。

    因为这是在(旧的,C11之前的)C中,所以内部联合必须在外部联合中指定一个字段名 struct union 匿名。选择这个名字可能很难。我倾向于使用单个字母,因为它几乎从来没有被孤立地引用过,因此从上下文中总是可以清楚地看到正在发生的事情。

    将值设置为整数的代码可能如下所示:

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

    可以直接返回s,并将其视为基本类型的值(您可以指定 s) 。

        2
  •  10
  •   Diomidis Spinellis    16 年前

    联合也常用于语言处理器(如编译器和解释器)的词法分析和解析阶段。这是我正在编辑的一个。

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

    union用于将语义值与词法分析器的标记和解析器的结果相关联。这种做法在语法生成器中非常常见,例如 ,它为它提供了明确的支持。工会可以持有任何一种价值观,但当时只能持有其中一种价值观。例如,在输入文件的任何一点上,您要么读取了字符常量(存储在 c ),或整数(存储在 i )或浮点数(存储在 d )。语法生成器根据正在处理的规则,为确定在任何时候存储哪些值提供了相当大的帮助。

        3
  •  10
  •   1800 INFORMATION    16 年前

    这里有一个我每天都用的小东西:

    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;
    };
    

    具有 VT_BYREF

    SAFEARRAY 类型-从C++中使用非常困难。

    VT_BYREF | VT_BSTR .

        4
  •  8
  •   starblue    16 年前

    请避免使用union进行“黑客攻击”,它们会导致移植性问题(端性、对齐问题)。

    • union的一个合法用途是在同一个位置存储不同的数据类型,最好使用标记,以便您知道它是哪种类型。请参见1800信息中的示例。

    • 不要使用union在数据类型之间进行转换,例如从整数转换为多个字节。为了便于携带,请使用shift和masking。

        5
  •  4
  •   Alaa M.    6 年前

    在有人将结构写入文件之前,它工作得很好,现在我们仅限于文件中使用的最大数据,因为即使有文件版本,也没有人更改它。。。。

        6
  •  3
  •   Community CDub    8 年前

    巧合的是,我只是在一个答案中使用了一个 here

        7
  •  3
  •   qwerty    16 年前
    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;
    

    使用联合黑客,我可以简单地制作一个对象向量。我相信这可以变得更干净…但它对我很有用-吻

        8
  •  1
  •   Alphaneo    16 年前
    #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;
    

    这是一种访问单词部分的简单方法。(a一旦完成,平台端部的任何变化也可以轻松处理)