nyteshade
nyteshade

Reputation: 2872

How do I initialize a struct of typedef'd unions in C?

So if I have code such as the following:

typedef union {
  long integer;
  float decimal;
  long *integerPtr;
  float *decimalPtr;
} Number;

typedef struct Point {
  Number x;
  Number y;
} Point;

How do I initialize this? Is it as simple as the following? Can I do this with a const as well?

Point p = { 100, 100 };
const Point p2 = { 640, 200 };

int someNum, someOtherNum;

Point p3 = { &someNum, &someOtherNum };

FYI: I am specifically targeting pre C99 C code.

Upvotes: 0

Views: 180

Answers (1)

Serge Ballesta
Serge Ballesta

Reputation: 148890

If you are specifically targetting old compilers, you will only be able to initialize the first element of the union. The nice part will be that you will not be bothered by the strict aliasing rule. Long story made short, here is what will happen:

  • initialize with integer values: all is fine the litteral or variables will be converted to long, so this will work fine:

    Point p = { 100, 100 };
    const Point p2 = { 640, 200 };
    
  • initialize with pointers: the long field will receive the value of the pointer converted to a long. What actually happens is unspecified, but on little endian common architecture if long is greater that pointer or on any architecture where long has same size as a pointer and where the representation of a pointer is its integer address, all will be fine. In fact you initialize the long value but as the pointer representation as same representation as the long, you get the expected result. So here again this works as expected (on a common architecture):

    int someNum, someOtherNum;
    Point p3 = { &someNum, &someOtherNum };
    
  • initialize with floats: no direct way because to conversion of a float to a long has not the same representation as a long. But as strict aliasing rule does not apply you can try to use type punning, provide the size of a long is the same as the size of a float:

    float f=12.5, g=1.;
    Point p4 = { *((long *) &f), *((long *) &g) };
    

Upvotes: 1

Related Questions