[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.c

Splitting union members in different struct

pozz

4/14/2011 12:24:00 PM

As someone probably rememeber, I use a quite old C compiler for an
embedded 16-bit processor with some limitations.
One of these regards the initialization of arbitrary members of union
or struct. For example, I can't do the following:

const struct {
int type;
union {
int x;
double y;
} u;
} mystruct = { TYPE_Y, {.y = 3} };

I was thinking to split a struct like the above in two different
struct and a "parent" struct:

typedef struct {
int type;
int x;
} mystruct_x;
typedef struct {
int type;
double y;
} mystruct_y;
typedef struct {
int type;
} mystruct;

The parent struct contains only the common members (in this case, only
the member type).
With the above definitions, I'd like to write something like:

const mystruct_x sx = { TYPE_X, 10 };
const mystruct_y sy = { TYPE_Y, 5.3 };
const mystruct *s;
...
s = (const mystruct *)&sx;
...
if (s->type == TYPE_X) {
const mystruct_x *sx = (const mystruct_x *)s;
printf("x=%d\n", sx->x);
} else if (s->type == TYPE_Y) {
const mystruct_y *sy = (const mystruct_y *)s;
printf("y=%3.1f\n", sy->y);
}

I'm asking if the cast from (mystruct_x *) to (mystruct *) and the
contrary is correctly interpreted.
3 Answers

China Blue Veins

4/14/2011 3:03:00 PM

0

In article <95c4ee04-716a-45ce-9d63-c7cd2c391091@d26g2000prn.googlegroups.com>,
pozz <pozzugno@gmail.com> wrote:

> As someone probably rememeber, I use a quite old C compiler for an
> embedded 16-bit processor with some limitations.
> One of these regards the initialization of arbitrary members of union
> or struct. For example, I can't do the following:
>
> const struct {
> int type;
> union {
> int x;
> double y;
> } u;
> } mystruct = { TYPE_Y, {.y = 3} };
>
> I was thinking to split a struct like the above in two different
> struct and a "parent" struct:
>
> typedef struct {
> int type;
> int x;
> } mystruct_x;
> typedef struct {
> int type;
> double y;
> } mystruct_y;
> typedef struct {
> int type;
> } mystruct;

Yes, it's safe. The address of the first field is guarenteed to be the same as
the address of the struct, so if the first field of each struct is the same,
(mystruc*)s will properly overlay the type of each (mystruct_x*)&sx and
(mystruct_y*&sy.

But it is not as safe if mystruct has more than one field. In that case, you
include mystruct itself, with its multiple fields, as the first field of the
other structs.

You use this to help implement single inheritance object oriented programning.

typdef struct {
type property;
type property;
...
} SuperClass;

typedef struct {
SuperClass super;
type property;
type property;
...
} DerivedClassA;

typedef struct {
SuperClass super;
type property;
type property;
...
} DerivedClassB;

typedef struct {
DerivedClassB super;
type property;
type property;
...
} SubClass;

--
Damn the living - It's a lovely life. I'm whoever you want me to be.
Silver silverware - Where is the love? At least I can stay in character.
Oval swimming pool - Where is the love? Annoying Usenet one post at a time.
Damn the living - It's a lovely life. I am in the Nile.

Fred

4/14/2011 3:12:00 PM

0

On Apr 14, 5:23 am, pozz <pozzu...@gmail.com> wrote:
> As someone probably rememeber, I use a quite old C compiler for an
> embedded 16-bit processor with some limitations.
> One of these regards the initialization of arbitrary members of union
> or struct. For example, I can't do the following:
>
>   const struct {
>     int type;
>     union {
>       int x;
>       double y;
>     } u;
>   } mystruct = { TYPE_Y, {.y = 3} };
>
> I was thinking to split a struct like the above in two different
> struct and a "parent" struct:
>
>   typedef struct {
>     int type;
>     int x;
>   } mystruct_x;
>   typedef struct {
>     int type;
>     double y;
>   } mystruct_y;
>   typedef struct {
>     int type;
>   } mystruct;
>
> The parent struct contains only the common members (in this case, only
> the member type).
> With the above definitions, I'd like to write something like:
>
>   const mystruct_x sx = { TYPE_X, 10 };
>   const mystruct_y sy = { TYPE_Y, 5.3 };
>   const mystruct *s;
>   ...
>   s = (const mystruct *)&sx;
>   ...
>   if (s->type == TYPE_X) {
>     const mystruct_x *sx = (const mystruct_x *)s;
>     printf("x=%d\n", sx->x);
>   } else if (s->type == TYPE_Y) {
>     const mystruct_y *sy = (const mystruct_y *)s;
>     printf("y=%3.1f\n", sy->y);
>   }
>
> I'm asking if the cast from (mystruct_x *) to (mystruct *) and the
> contrary is correctly interpreted.

Copy how the Unix XEvent structures do it:

typedef struct {
int type;
} MyStructAny;

typedef struct {
int type;
int x;
} MyStructInt;

typedef struct {
int type;
double y;
} MyStructDouble;

typedef union myStruct {
int type;
MyStructAny my_any;
MyStructInt my_a;
MyStructDouble my_b;
} MyStruct;

const MyStructInt sx = { TYPE_X, 10 };
const MyStructDouble sy = { TYPE_Y, 5.3 };
const MyStruct *s;
...
s = (const MyStruct *)&sx;
...
if (s->type == TYPE_X) {
const MyStructInt *sx = (const MyStructInt *)s;
printf("x=%d\n", sx->x);
} else if (s->type == TYPE_Y) {
const MyStructDouble *sy = (const MyStructDouble *)s;
printf("y=%3.1f\n", sy->y);
}

--
Fred K

pozz

4/15/2011 7:01:00 AM

0

On 14 Apr, 17:12, Fred <fred.l.kleinschm...@boeing.com> wrote:
> Copy how the Unix XEvent structures do it:
>
> typedef struct {
>    int type;
>
> } MyStructAny;
>
> typedef struct {
>    int type;
>    int x;
>
> } MyStructInt;
>
> typedef struct {
>    int type;
>    double y;
>
> } MyStructDouble;
>
> typedef union myStruct {
>    int type;
>    MyStructAny my_any;
>    MyStructInt my_a;
>    MyStructDouble my_b;
>
> } MyStruct;

Uh? What is this union where you mix the type and the various struct?
When I want to access just to the type member (because I don't know
the
exact type of the struct), I can use just MyStructAny, can't I?

>   const MyStructInt sx = { TYPE_X, 10 };
>   const MyStructDouble sy = { TYPE_Y, 5.3 };
>   const MyStruct *s;
>   ...
>   s = (const MyStruct *)&sx;
>   ...
>   if (s->type == TYPE_X) {
>     const MyStructInt *sx = (const MyStructInt *)s;
>     printf("x=%d\n", sx->x);
>   } else if (s->type == TYPE_Y) {
>     const MyStructDouble *sy = (const MyStructDouble *)s;
>     printf("y=%3.1f\n", sy->y);
>   }

I would have wrote:

const MyStructInt sx = { TYPE_X, 10 };
const MyStructDouble sy = { TYPE_Y, 5.3 };
const MyStructAny *s;
...
s = (const MyStructAny *)&sx;
...
if (s->type == TYPE_X) {
const MyStructInt *sx = (const MyStructInt *)s;
printf("x=%d\n", sx->x);
} else if (s->type == TYPE_Y) {
const MyStructDouble *sy = (const MyStructDouble *)s;
printf("y=%3.1f\n", sy->y);
}

so without using the MyStruct at all.

Anyway I'm reading about XEvent structure of Xlib and I found it is
really a union:

typedef struct {
int type;
unsigned long serial; /* # of last request processed by server */
Bool send_event; /* true if this came from a SendEvent request */
Display *display; /* Display the event was read from */
Window window;
} XAnyEvent;
typedef union _XEvent {
int type; /* must not be changed */
XAnyEvent xany;
XKeyEvent xkey;
XButtonEvent xbutton;
...
} XEvent;

But I can't understand. What is the goal to use union to declare the
"parent" class XEvent? I think XEvent is used just to access the type
or the members in xany. Wouldn't be sufficient to use XAnyEvent as
XEvent?