tags:

views:

1211

answers:

17

I have a example with me where in which the alignment of a type is guaranteed, union max_align . I am looking for a even simpler example in which union is used practically, to explain my friend.

A: 

do you mean something like this ?

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

ADDED:

I have recently used this on our AIX machine to transform the 64bit machine-indentifier into a byte-array.

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
yes but I want were it is practically applied, something like max_align
yesraaj
If you use something like this, you should take care of the order of bytes (endianess). Which means that this code may work on a machine (big endian) and doesn't work on the other machine(little endian)
Yousf
It work's on BE and on LE machines. Only the results are different :-)
@yesraaj: I have recently used this on our AIX machine to transform the 64bit machine-indentifier into a byte-array. Note: this machine-identifier is something AIX specific.
A: 

Example:

When using different socket types, but you want a comon type to refer.

Xolve
+1  A: 
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;
};
ironic
I know how to use union, my friend does too, but I want were it is used most commonly
yesraaj
Maybe this helps: http://cplus.about.com/od/learningc/ss/lowlevel_9.htm
ironic
A: 

Another example more: to save doing castings.

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

instead of:

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));
}
fortran
using a union to cast like this is technically undefined behaviour (although i'm unaware of any implementations which don't actually do what you want here)
jk
A common term for this technique is "type punning"
fbrereto
@jk The very same undefined behaviour of getting the address, casting to a int pointer and then getting the contents. The only thing undefined here should be the endianness of the float, that is not specified by any standard.
fortran
This technique blows up when your longs are 64 bit and your floats are not. e.g. linux 64 bit.
nos
@nos it won't "blow up", you'll keep getting the binary value of the float in either the lower or the upper part of the int (depending on the endiannes) and in the other, maybe trash... you can use a fixed size type if you wish, but this was just an example, not production quality code.
fortran
I consider my applicatons to "blow up" when it starts producing or processing garbage :-)
nos
+12  A: 

I usually use unions when parsing text. I use something like this:

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

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->dataType){
       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;
   }
}

If you want to see how unions are used HEAVILY, check any code using flex/bison. For example see splint, it contains TONS of unions.

Yousf
+3  A: 

For accessing registers or I/O ports bytewise as well as bitwise by mapping that particular port to memory, see the example below:

    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
wrapperm
Never use this if you have to handle big/little endian conversions
mouviciel
@mouviciel: This is not affected by endianness... can you please support your comment, if so..?
wrapperm
From the C standard: "The order of allocation of bit-fields within a unit (high-order to low-order or low-order to high-order) is implementation-defined. The alignment of the addressable storage unit is unspecified."
Alok
However, in many cases registers or I/O ports *are* platform-specific, so platform-independent code isn't such a concern. Though I suppose you might write a driver for some hardware that is used on both big-endian and little-endian machines (e.g. a Linux driver for a graphics chip)... in that case you'd know what you're doing I'm sure.
Craig McQueen
The alignment of the addressable storage unit can be easily determined by a simple program... actually speaking you should have an idea about the architectural endianness and stuff like that before coding for a particular platform...
wrapperm
+3  A: 

I've typically used unions where you want to have different views of the data e.g. a 32-bit colour value where you want both the 32-bit val and the red,green,blue and alpha components

struct rgba
{
  unsigned char r;
  unsigned char g;
  unsigned char b;
  unsigned char a;
};

union  
{
  unsigned int val;
  rgba components;
}colorval32;

NB You could also achieve the same thing with bit-masking and shifting i.e

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

but I find the union approach more elegant

zebrabox
But `struct rgba` may have padding, and even without padding, `sizeof(unsigned int)` may or may not be equal to `sizeof(struct rgba)` (4 for no padding). I.e., you probably don't want to do this.
Alok
@Alok: Not to mention that the `struct` will have `r`, `g`, `b`, and `a` in order (with or without padding), while the `unsigned int` byte order will depend on endianness. In other words, this code is not portable and may fail in odd ways when compiling on another processor.
David Thornley
Do note that (standard) C does not support this - assigning to one member in a union and then reading from another member is undefined behavior. Compilers/systems implementations do commonly support this though in their own specific ways.
nos
Thanks for the comments all. As you say this isn't portable ( nor is it intended to be) and relies on many assumptions which I didn't make clear in the post. Typically I wouldn't be using unsigned int but something like a typedef uint32_t i.e where I knew it was 32-bits. I'll amend my post to make this clearer
zebrabox
In addition to the portability issues, it's also a great way to confuse the compiler with potential aliasing, forcing it to skip a load of otherwise useful optimizations.
jalf
A: 

For convenience, I use unions to let me use the same class to store xyzw and rgba values

#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
Tom J Nowell
+1  A: 

Unions are useful if you have different kinds of messages, in which case you don't have to know in any intermediate levels the exact type. Only the sender and receiver need to parse the message actual message. Any other levels only really need to know the size and possibly sender and/or receiver info.

Makis
Isn't this what polymorphism is for? A base class for the common message content, then each message is a specialization of the base class.
Thomas Matthews
@Thomas: you don't have classes in C.
Adriano Varoli Piazza
A: 

Many examples of unions can be found in <X11/Xlib.h>. Few others are in some IP stacks (in BSD <netinet/ip.h> for instance).

As a general rule, protocol implementations use union construct.

mouviciel
+1  A: 

I've used sometimes unions this way

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

Then you could declare arrays of different kind of values, storing more or less efficiently the data, and make some "polimorph" operations like:

 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;
    }
 }
Khelben
A: 

Here is another example where a union could be useful.

(not my own idea, I have found this on a document discussing c++ optimizations)

begin-quote

.... Unions can also be used to save space, e.g.

first the non-union approach:

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

Here it is possible to use the same memory area for a and b because their live ranges do not overlap. You can save a lot of cpu-cache space by joining a and b in a union:

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

Using a union is not a safe programming practice, of course, because you will get no warning from the compiler if the uses of a and b overlap. You should use this method only for big objects that take a lot of cache space. ...

end-qoute

A: 

Unions can also be useful when type punning, which is desirable in a select few places (such as some techniques for floating-point comparison algorithms).

fbrereto
+3  A: 

In the Windows world, unions are commonly used to implement tagged variants, which are (or were, before .NET?) one standard way of passing data between COM objects.

The idea is that a union type can provide a single natural interface for passing arbitrary data between two objects. Some COM object could pass you a variant (e.g. type VARIANT or _variant_t) which could contain either a double, float, int, or whatever.

If you have to deal with COM objects in Windows C++ code, you'll see variant types all over the place.

Nate Kohl
+1  A: 
  • When reading serialized data that needs to be coerced into specific types.
  • When returning semantic values from lex to yacc. (yylval)
  • When implementing a polymorphic type, especially one that reads a DSL or general language
  • When implementing a dispatcher that specifically calls functions intended to take different types.
DigitalRoss
A: 

Recently I think I saw some union used in vector programming. vector programming is used in intel MMX technology, GPU hardware, IBM's Cell Broadband Engine, and others.

a vector may correspond to a 128 bit register. It is very commonly used for SIMD architecture. since the hardware has 128-bit registers, you can store 4 single-precision-floating points in a register/variable. an easy way to construct, convert, extract individual elements of a vector is to use the union.

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

if you take a path in PlayStation 3 Multi-core Programming, or graphics programming, a good chance you'll face more of these stuffs.

afriza
Do note that writing to one member of a union then reading from another leads to undefined behavior.
GMan
+1  A: 

SDL uses an union for representing events: http://www.libsdl.org/cgi/docwiki.cgi/SDL_Event.

Bastien Léonard