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

C:实际上在哪里使用union?

  •  30
  • yesraaj  · 技术社区  · 16 年前

    18 回复  |  直到 13 年前
        1
  •  33
  •   Koray Tugay    11 年前

    我通常在解析文本时使用联合。我用这样的方式:

    typedef enum DataType { INTEGER, FLOAT_POINT, STRING } DataType ;
    
    typedef union DataValue
    {
        int v_int;
        float v_float;
        char* v_string;
    }DataValue;
    
    typedef struct DataNode
    {
        DataType type;
        DataValue value;
    }DataNode;
    
    void myfunct()
    {
        long long temp;
        DataNode inputData;
    
        inputData.type= read_some_input(&temp);
    
        switch(inputData.type)
        {
            case INTEGER: inputData.value.v_int = (int)temp; break;
            case FLOAT_POINT: inputData.value.v_float = (float)temp; break;
            case STRING: inputData.value.v_string = (char*)temp; break;
        }
    }
    
    void printDataNode(DataNode* ptr)
    {
       printf("I am a ");
       switch(ptr->type){
           case INTEGER: printf("Integer with value %d", ptr->value.v_int); break;
           case FLOAT_POINT: printf("Float with value %f", ptr->value.v_float); break;
           case STRING: printf("String with value %s", ptr->value.v_string); break;
       }
    }
    

    flex bison . 例如见 splint ,它包含数吨的接头。

        2
  •  6
  •   zebrabox    16 年前

    我通常使用联合,您希望对数据有不同的视图

    struct rgba
    {
      unsigned char r;
      unsigned char g;
      unsigned char b;
      unsigned char a;
    };
    
    union  
    {
      unsigned int val;
      rgba components;
    }colorval32;
    

    #define GETR(val) ((val&0xFF000000) >> 24)
    

    但我觉得工会的做法更优雅

        3
  •  5
  •   wrapperm    16 年前

    要通过将特定端口映射到内存来按字节和按位访问寄存器或I/O端口,请参见以下示例:

        typedef Union
    {
      unsigned int a;
    struct {
      unsigned bit0 : 1,
               bit1 : 1,
               bit2 : 1,
               bit3 : 1,
               bit4 : 1,
               bit5 : 1,
               bit6 : 1,
               bit7 : 1,
               bit8 : 1,
               bit9 : 1,
               bit10 : 1,
               bit11 : 1,
               bit12 : 1,
               bit13 : 1,
               bit14 : 1,
               bit15 : 1
    } bits;
    } IOREG;
    
    # define PORTA (*(IOREG *) 0x3B)
    ...
    unsigned int i = PORTA.a;//read bytewise
    int j = PORTA.bits.bit0;//read bitwise
    ...
    PORTA.bits.bit0 = 1;//write operation
    
        4
  •  3
  •   Nate Kohl    16 年前

    在Windows世界中, unions 通常用于实现 tagged variants ,这是(或曾经是.NET之前的?)在 COM objects .

    这个想法是 union 类型可以为在两个对象之间传递任意数据提供单一的自然接口。某些COM对象可能会向您传递变量(例如类型 VARIANT _variant_t double , float int ,或者别的什么。

    如果你必须处理Windows C++代码中的COM对象,你会看到所有地方都有不同的类型。

        5
  •  2
  •   ironic    16 年前
    struct cat_info
    {
    int legs;
    int tailLen;
    };
    
    struct fish_info
    {
    bool hasSpikes;
    };
    
    
    union 
    {
    fish_info fish;
    cat_info cat;
    } animal_data;
    
    struct animal
    {
    char* name;
    int animal_type;
    animal_data data;
    };
    
        6
  •  2
  •   Makis    16 年前

    如果您有不同类型的消息,则联合非常有用,在这种情况下,您不必知道任何中间级别的确切类型。只有发送方和接收方需要解析消息-实际消息。任何其他级别只需要知道大小以及可能的发送方和/或接收方信息。

        7
  •  2
  •   Bastien Léonard    16 年前
        8
  •  1
  •   anon anon    16 年前

    union {
       long long a;
       unsigned char b[sizeof(long long)];
    } long_long_to_single_bytes;
    

    补充 :

    std::string getHardwareUUID(void) {
    #ifdef AIX
       struct xutsname m; // aix specific struct to hold the 64bit machine id
       unamex(&b);        // aix specific call to get the 64bit machine id
       long_long_to_single_bytes.a = m.longnid;
       return convertToHexString(long_long_to_single_bytes.b, sizeof(long long));
    #else // Windows or Linux or Solaris or ...
       ... get a 6byte ethernet MAC address somehow and put it into mac_buf
       return convertToHexString(mac_buf, 6);
    #endif
    
        9
  •  1
  •   anon anon    16 年前

    这是另一个工会可能有用的例子。

    c++ optimizations )

    开始报价

    .... 还可以使用联合来节省空间,例如。

    第一,非工会办法:

    void F3(bool useInt) {
        if (y) {
            int a[1000];
            F1(a);  // call a function which expects an array of int as parameter
        }
        else {
            float b[1000];
            F2(b);  // call a function which expects an array of float as parameter
        }
    }
    

    cpu缓存空间 通过加入a和b的联盟:

    void F3(bool useInt) {
    
        union {
            int a[1000];
            float b[1000];
        };
    
        if (y) {
            F1(a);  // call a function which expects an array of int as parameter
        }
        else {
            F2(b);  // call a function which expects an array of float as parameter
        }
    }
    

    当然,使用联合不是一种安全的编程实践,因为您不会得到任何好处 如果a和b的使用重叠,编译器发出警告。您应该只使用此方法

    库特终点

        10
  •  1
  •   Craig McQueen Dr. Watson    16 年前

    我有时用这种方式

    //Define type of structure
    typedef enum { ANALOG, BOOLEAN, UNKNOWN } typeValue_t;
    //Define the union
    typedef struct  {
      typeValue_t typeValue;
      /*On this structure you will access the correct type of
        data according to its type*/
      union {
        float ParamAnalog;
        char  ParamBool;
      };
    } Value_t;
    

     void printValue ( Value_t value ) {
        switch (value.typeValue) {
           case BOOL:
              printf("Bolean: %c\n", value.ParamBool?'T':'F');
              break;
           case ANALOG:
              printf("Analog: %f\n", value.ParamAnalog);
              break;
           case UNKNOWN:
              printf("Error, value UNKNOWN\n");
              break;
        }
     }
    
        11
  •  1
  •   DigitalRoss    16 年前
    • 从返回语义值时 lex yacc . ( yylval )
    • 当实现一个调度器时,该调度器专门调用打算采用不同类型的函数。
        12
  •  1
  •   Afriza N. Arief    16 年前

    最近我想我看到了一些工会在 vector programming intel MMX technology IBM's Cell Broadband Engine 等。

    向量可以对应于128位寄存器。这是非常常用的 SIMD 建筑学由于硬件有128位寄存器,您可以在寄存器/变量中存储4个单精度浮点。构造、转换和提取向量各个元素的一种简单方法是使用并集。

    typedef union {
        vector4f vec; // processor-specific built-in type
        struct { // human-friendly access for transformations, etc
            float x;
            float y;
            float z;
            float w;
        };
        struct { // human-friendly access for color processing, lighting, etc
            float r;
            float g;
            float b;
            float a;
        };
        float arr[4]; // yet another convenience access
    } Vector4f;
    
    int main()
    {
        Vector4f position, normal, color;
        // human-friendly access
        position.x = 12.3f;
        position.y = 2.f;
        position.z = 3.f;
        position.w = 1.f;
    
        // computer friendly access
        //some_processor_specific_operation(position.vec,normal.vec,color.vec);
        return 0;
    }
    

    如果你选择PlayStation 3多核编程或图形编程,你很有可能会遇到更多这样的问题。

        13
  •  1
  •   user69820 user69820    15 年前

    Variant 我相信VBScript中的数据类型是作为 Union . 下面的代码是一个简化的示例,摘自另一篇文章 here

    struct tagVARIANT
    {
        union 
        {
            VARTYPE vt;
            WORD wReserved1;
            WORD wReserved2;
            WORD wReserved3;
            union 
            {
                LONG lVal;
                BYTE bVal;
                SHORT iVal;
                FLOAT fltVal;
                DOUBLE dblVal;
                VARIANT_BOOL boolVal;
                DATE date;
                BSTR bstrVal;
                SAFEARRAY *parray;
                VARIANT *pvarVal;
            };
        };
    };
    

    实际实现(如文章所述)见 oaidl.h

        14
  •  0
  •   Xolve    16 年前

    例子:

    当使用不同的套接字类型时,但您希望引用一个comon类型。

        15
  •  0
  •   fortran    16 年前

    另一个例子更多:保存做铸件。

    typedef union {
      long int_v;
      float float_v;
    } int_float;
    
    void foo(float v) {
      int_float i;
      i.float_v = v;
      printf("sign=%d exp=%d fraction=%d", (i.int_v>>31)&1, ((i.int_v>>22)&0xff)-128, i.int_v&((1<<22)-1));
    }
    

    而不是:

    void foo(float v) {
      long i = *((long*)&v);
      printf("sign=%d exp=%d fraction=%d", (i>>31)&1, ((i>>22)&0xff)-128, i&((1<<22)-1));
    }
    
        16
  •  0
  •   Tom J Nowell    16 年前

    为了方便起见,我使用联合让我使用同一个类来存储xyzw和rgba值

    #ifndef VERTEX4DH
        #define VERTEX4DH
    
        struct Vertex4d{
    
            union {
                double x;
                double r;
            };
            union {
                double y;
                double g;
            };
            union {
                double z;
                double b;
            };
            union {
                double w;
                double a;
            };
    
            Vertex4d(double x=0, double y=0,double z=0,double w=0) : x(x), y(y),z(z),w(w){}
        };
    
    #endif
    
        17
  •  0
  •   mouviciel    16 年前

    许多工会的例子可以在 <X11/Xlib.h> . 在某些IP堆栈中(在BSD中)很少有其他IP堆栈 <netinet/ip.h>

    作为一般规则,协议实现使用union构造。

        18
  •  0
  •   fbrereto    16 年前

    type punning ,这在一些特定的地方是可取的(例如 floating-point comparison 算法)。

    推荐文章