properly using unions.

P

pereges

Hello, can some one please guide me a little into using unions. I read
about unions in K & R but I am finding it difficult to apply to my
problem at hand. I want to save up some space by using unions . My
questions are :

1. Is it dangerous to use unions ? Is it worth the trouble if I want
to save memory ? Are they error prone ?

2. I read that it is not possible to access more than 1 member at any
instant from a union. What does this actually mean ? I cannot use two
members simultaneously in a single statement ?
 
R

rahul

Hello, can some one please guide me a little into using unions. I read
about unions in K & R but I am finding it difficult to apply to my
problem at hand. I want to save up some space by using unions .

Unions aren't generally about saving space. They are used in a
situation in which you don't use all the members but access them based
on some condition.

My
questions are :

1. Is it dangerous to use unions ? Is it worth the trouble if I want
to save memory ? Are they error prone ?

If it's about saving memory, I am afraid its going to a lot of trouble
and it's not worth it.

2. I read that it is not possible to access more than 1 member at any
instant from a union. What does this actually mean ? I cannot use two
members simultaneously in a single statement ?

In an union, the space allocated equals the size of biggest member
(and any padding done by the implementation).
union _foo {
int bar;
double baz;
}foo;

sizeof(union foo) will give you sizeof(double) and maybe some padding.
Both bar and baz share the same memory space. They are distinct
members but they share the same memory space.

Consider :

#define DOUBLE 1
#define STRING 2
#define INT 3

struct _node {
int type;
union {
double d;
char a[10];
int i;
}
_node *next;
}node;
struct node *list;

/* ... */
void *getElement(void) {
switch (list->type) {
case DOUBLE:
return &(list->d);
case STRING:
return list->a;
case INT:
return &(list->i);
default:
return null;
}

This is just a skeleton. In this scenario, you are using unions to
have a hetrogenous list. There are some other scenarios but I don't
think its worth playing tricks with unions just to save space.
 
S

santosh

rahul wrote:

In an union, the space allocated equals the size of biggest member
(and any padding done by the implementation).
union _foo {
int bar;
double baz;
}foo;

sizeof(union foo) will give you sizeof(double) and maybe some padding.

Correct me if I'm wrong, but isn't it perfectly conforming for an
implementation to have sizeof(int) > sizeof(double)?

<snip>
 
R

rahul

rahul wrote:
Correct me if I'm wrong,
You are not.
but isn't it perfectly conforming for an
implementation to have sizeof(int) > sizeof(double)?
It is perfectly conforming for an implementation to have sizeof(int) >
sizeof(double).


Correction:
sizeof(union foo) wil give you whatever is greater of sizeof(int) and
sizeof(double) and padding, if any.
 
C

Chris Dollin

rahul said:
Unions aren't generally about saving space. They are used in a
situation in which you don't use all the members but access them based
on some condition.

There seem to be two ways of using unions.

One is type-punning, where you write a value into on member of
the union and read it from another with a different type. This
is useful much less often than one might suppose, because the
Standard leaves undefined rather a lot of possibilities. The
wise man will often go another way.

The other way is when the union is expressing the idea that the
desired value is either this, or that, or the other, and which
it is, is "based on some condition". In this case, it seems to
me that the union /is/ about saving space, since otherwise you
could equally well use a struct.

--
"Its deductive method was holistic, totalising, /Perdido Street Station/
and inconstant."

Hewlett-Packard Limited registered office: Cain Road, Bracknell,
registered no: 690597 England Berks RG12 1HN
 
J

Johannes Bauer

rahul said:
In an union, the space allocated equals the size of biggest member
(and any padding done by the implementation).

Please quote from the standard as I do not think this is true.

Lets say we have a union x

union x {
int foo;
double bar;
};

then the following is okay:

x.foo = 4;
printf("%d\n", x.foo);
x.bar = 3.1415;
printf("%lf\n", x.bar);

But this is not

x.foo = 4
printf("%lf\n", x.bar);

As only one member is valid to be read which has been written. The
standard would not say that IMHO if it were not possible for an
implementation to just concatenate the elements, i.e. making a union
equal to a struct.

Regards,
Johannes
 
R

Richard Tobin

Johannes Bauer said:
As only one member is valid to be read which has been written. The
standard would not say that IMHO if it were not possible for an
implementation to just concatenate the elements, i.e. making a union
equal to a struct.

But it does. C99 6.7.2.1: "The size of a union is sufficient to contain
the largest of its members ... A pointer to a union object, suitably
converted, points to each of its members".

-- Richard
 
E

ediebur

Hello, can some one please guide me a little into using unions. I read
about unions in K & R but I am finding it difficult to apply to my
problem at hand. I want to save up some space by using unions . My
questions are :

1. Is it dangerous to use unions ? Is it worth the trouble if I want
to save memory ? Are they error prone ?

2. I read that it is not possible to access more than 1 member at any
instant from a union. What does this actually mean ? I cannot use two
members simultaneously in a single statement ?

I have lots of experience C programming ( although not recent -- I
hope things haven't changed that much) and to me, clarity was always a
priority. I guess I was never in a memory starved environment ( well,
I did have to use overlays in a PDP 11). I never saw a use for unions.
Except for type punning-- something I was aware of but never had to
use.
 
B

Bartc

I have lots of experience C programming ( although not recent -- I
hope things haven't changed that much) and to me, clarity was always a
priority. I guess I was never in a memory starved environment ( well,
I did have to use overlays in a PDP 11). I never saw a use for unions.
Except for type punning-- something I was aware of but never had to
use.

You haven't lived. I have used the following struct with unions, and even
then I have to rely on half-a-dozen helper macros to get the variable field
accesses I need. This struct is 16 bytes but looks bigger:

typedef struct svarrec {
short int dtype; /* These 4 bytes also accessed as int using asint()
*/
char copy;
char spare;

union { /* .value */
int value;
int xvalue; /* use asreal() to access .xvalue/.xvalue2 together
*/
int dvalue; /* use asint64() to access .dvalue/.dvalue2 together
*/
char *svalue;
char *ptr;
struct svarrec *vptr;
int *retaddr;
int first;
};

union { /* .value2 */
int value2;
int length;
int upper;
int frame;
int last;
int xvalue2; /* top half of double at .xvalue */
int dvalue2; /* top half of int64 at .dvalue */
short int rdoti;
short int rlength; /* in msw, use asmsw() macro */
};

union { /* .value3 */
int value3;
int lower;
int tag;
int pos;
int doti;
int nvars;
short int elemtype;
short int shortlower; /* in msw, use asmsw() macro */
};

} varrec;

(Note: this makes use of anonymous unions, which I think is not standard.
Using named unions would really obfuscate the code with extraneous field
names.)
 
J

Johannes Bauer

Richard said:
But it does. C99 6.7.2.1: "The size of a union is sufficient to contain
the largest of its members ... A pointer to a union object, suitably
converted, points to each of its members".

Sufficient means at least as large as the largest member, so no hint
there. But the second constraint means that all objects within the union
have to start in the same memory region - so that's something one cannot
argue with. The use of a struct instead of a union by the compiler is
therefore definitely forbidden.

Thanks for the pointer.

Regards,
Johannes
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,819
Latest member
masterdaster

Latest Threads

Top