Application of Union in C

S

samrox

U really need to read up a C book mate...its quite a stupid question!

Newton was right, earth sucks!
 
C

Chris Dollin

samrox said:
U really need to read up a C book mate...its quite a stupid question!

/You/ really need to lean how to quote (and how to be polite):

And it's not a stupid question. The OP is probably better off trying to
learn it from their book or their co-students or even Google -- but the
question isn't stupid.

[I'm not answering it because I think there are people who will do a better
job than I would today.]
 
B

balasam

samrox said:
U really need to read up a C book mate...its quite a stupid question!

Newton was right, earth sucks!
Dear friend,
I studied the second edition of C programming language that is
wirtten by "Kernigan" and "Dennis Ritchie".I studied the union is
mainly used in a compiler symbol table and It is also used in printf
and scanf library function,etc.,.Please note i want other than these
points and important application of UNION.

Thanks for your reply!!!!!!!!!!!!!
bye bye!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
R

rrs.matrix

here is a very simple example to explain the use of unions in C
union test
{
int x;
char c;
};

int main()
{
union test t;
t.x=65;
printf("\n%c\n",t.c);
return 0;
}
output:
A

now here's what is happening
storage space is provided for the largest datatype of the union.
in our example it is x..(int -4by and char -1by)
when we assign 65 to x the binary equivalent of 65 is stored in memory.
the char equivalent of 65 is A
hence when we try to access c the char 'A' is printed to the screen.
memory allocation:

int
byte 1 byte 2 byte 3 byte 4
-------------- -------------- -------------- -------------- => 65
00000000 00000000 00000000 01000001

char
--------------- => A
01000001
 
N

Naresh

here is a very simple example to explain the use of unions in C
union test
{
int x;
char c;
};

int main()
{
union test t;
t.x=65;
printf("\n%c\n",t.c);
return 0;
}
output:
A


Can we use floats also? I know it is stored as exponent and mantissa in
bytes. But I dont know if it can be use (or is valid in C standard) in
union also. plz guide.
 
A

Abdo Haji-Ali

Naresh said:
Can we use floats also? I know it is stored as exponent and mantissa in
bytes. But I dont know if it can be use (or is valid in C standard) in
union also. plz guide.

Of course, however you need to be careful... As you mentioned floats
are represented as exponent and mantissa, unlike integers which are
represented using the 2's complement. Consider a union like this one:
union
{
int iFloatBits;
float fSomeNumber;
}

If you check the value of iFloatBits, it won't be the integer part of
fSomeNumber, but rather the integer number which is produced by the
bits of fSomeNumber...

Hope that helped,
Abdo Haji-Ali
Progammer
In|Framez
 
O

osmium

Naresh said:
Can we use floats also? I know it is stored as exponent and mantissa in
bytes. But I dont know if it can be use (or is valid in C standard) in
union also. plz guide.

K&R answers that question. The answer is yes. A union could be used to
deconstruct a float, presuming you have a mapping of the float as used on
your platform.

Please spell please as "please".
 
V

Vladimir S. Oka

Abdo said:
Of course, however you need to be careful... As you mentioned floats
are represented as exponent and mantissa, unlike integers which are
represented using the 2's complement. Consider a union like this one:
union
{
int iFloatBits;
float fSomeNumber;
}

If you check the value of iFloatBits, it won't be the integer part of
fSomeNumber, but rather the integer number which is produced by the
bits of fSomeNumber...

Probably the best way to explore bit-representation of `float`/`double`
is to use a `union` with a `char` array:

union
{
char b[SIZEOF_DOUBLE];
double d;
}

Where SIZEOF_DOUBLE is, obviously == `sizeof(double)`.

Reading out values of `b[index]` is always OK, as `char` cannot have
trap representation. Be careful if you want to experiment by writing to
`b[index]`, as it may create a trap representation of `d`. This will be
a problem once `d` is read (provided it assumed a trap value).

As an aside, unless you have a very good specific reason, use `double`
instead of `float`.
 
A

Abdo Haji-Ali

Vladimir said:
As an aside, unless you have a very good specific reason, use `double`
instead of `float`.

Any logical reason for this? I always use floats, especially if I don't
need the extra precision of double, also many third part libraries
(Like DirectX and OpenGL) use them...

Abdo Haji-Ali
Programmer
In|Framez
 
R

Robert Latest

On 19 Apr 2006 06:52:13 -0700,
in Msg. said:
union
{
char b[SIZEOF_DOUBLE];
double d;
}

Where SIZEOF_DOUBLE is, obviously == `sizeof(double)`.

why not just write

char b[sizeof(double)]; ?

sizeof is an operator, not a function.

robert
 
R

regis

here is a very simple example to explain the use of unions in C
union test
{
int x;
char c;
};

int main()
{
union test t;
t.x=65;
printf("\n%c\n",t.c);
return 0;
}
output:
A

now here's what is happening
storage space is provided for the largest datatype of the union.
in our example it is x..(int -4by and char -1by)
when we assign 65 to x the binary equivalent of 65 is stored in memory.
the char equivalent of 65 is A
hence when we try to access c the char 'A' is printed to the screen.
memory allocation:

int
byte1 byte 2 byte 3 byte 4
-------- -------- -------- -------- => 65
00000000 00000000 00000000 01000001
char
-------- => A
01000001

The schema seems wrong.
A pointer to a union object, suitably converted,
points to each of its members, so there cannot be
3 padding bytes before the char field c.

Reading a field in a union leads to implementation defined
behavior when this field is not the most recently assigned
among the fields of this union.

In particular, your code will behave differently
on big endian and little endian architectures.
Executed on a Sun with gcc, your code yields '\0' in
the char field c.

Two common scenarios for 4 byte ints, are:

byte 1 byte 2 byte 3 byte 4
-------- -------- -------- -------- => 65 as big endian int
00000000 00000000 00000000 01000001
-------- => '\0'
00000000

byte 1 byte 2 byte 3 byte 4
-------- -------- -------- -------- => 65 as little endian int
01000001 00000000 00000000 00000000
-------- => 'A'
01000001
 
V

Vladimir S. Oka

Abdo said:
Any logical reason for this? I always use floats, especially if I don't
need the extra precision of double, also many third part libraries
(Like DirectX and OpenGL) use them...

Well, I'd say that the floats are not really that precise? Why would
extra precision hurt.

If you have a maths coprocessor, there may be no performance penalty in
using doubles. Actually, if your coprocessor's native data size is
larger then the size of `float`, then using them may incur performance
penalty, as they'll have to be massaged in and out.

In case you're on a small (e.g. embedded) system without hardware
floating point support, and you worry about performance, you may be
better of with fixed point.

Obviously, depending on the task and system at hand YMMV.
 
K

Keith Thompson

Vladimir S. Oka said:
Probably the best way to explore bit-representation of `float`/`double`
is to use a `union` with a `char` array:

union
{
char b[SIZEOF_DOUBLE];
double d;
}

Where SIZEOF_DOUBLE is, obviously == `sizeof(double)`.

Reading out values of `b[index]` is always OK, as `char` cannot have
trap representation. Be careful if you want to experiment by writing to
`b[index]`, as it may create a trap representation of `d`. This will be
a problem once `d` is read (provided it assumed a trap value).

It's much better to use unsigned char rather than char (which can be
either signed or unsigned). I think you're right that char can't have
trap representations, but it can have padding bits; unsigned char
cannot.

In general, storing a value in one member of a union and then reading
another member is dangerous unless the member you read is an array of
unsigned char. Using a union to overlay the representations of two
different types is common, but it's not really supported by the
standard.

Another common use of unions is to implement something like Pascal's
variant records. For example:

enum type { INT, DOUBLE, POINTER };
struct variant {
enum type current_type;
union {
int i;
double d;
void *p;
}
}

The value of the current_type member indicates which union member is
currently active.
 
V

Vladimir S. Oka

Keith Thompson opined:
Vladimir S. Oka said:
Probably the best way to explore bit-representation of
`float`/`double` is to use a `union` with a `char` array:

union
{
char b[SIZEOF_DOUBLE];
double d;
}

Where SIZEOF_DOUBLE is, obviously == `sizeof(double)`.

Reading out values of `b[index]` is always OK, as `char` cannot have
trap representation. Be careful if you want to experiment by writing
to `b[index]`, as it may create a trap representation of `d`. This
will be a problem once `d` is read (provided it assumed a trap
value).

It's much better to use unsigned char rather than char (which can be
either signed or unsigned). I think you're right that char can't
have trap representations, but it can have padding bits; unsigned
char cannot.

You're right about the `unsigned char`, it is better. For all the
reasons given.
In general, storing a value in one member of a union and then reading
another member is dangerous unless the member you read is an array of
unsigned char. Using a union to overlay the representations of two
different types is common, but it's not really supported by the
standard.

Another common use of unions is to implement something like Pascal's
variant records. For example:

enum type { INT, DOUBLE, POINTER };
struct variant {
enum type current_type;
union {
int i;
double d;
void *p;
}
}

The value of the current_type member indicates which union member is
currently active.

I wish I had more time at the office... ;-)

--
"Nature abhors a Vacuum"

-- Brian Behlendorf on OSS (Open Sources, 1999 O'Reilly and
Associates)

<http://clc-wiki.net/wiki/Introduction_to_comp.lang.c>
 
V

void * clvrmnky()

balasam said:
Dear friend,
I studied the second edition of C programming language that is
wirtten by "Kernigan" and "Dennis Ritchie".I studied the union is
mainly used in a compiler symbol table and It is also used in printf
and scanf library function,etc.,.Please note i want other than these
points and important application of UNION.

Thanks for your reply!!!!!!!!!!!!!
bye bye!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Your "1" key is sticking.
 
N

Neil

balasam said:
I want what is the application of union in C.Please explain


Two use that I have seen.
1) to save space. Since the data is overlaid the same space is reused.
Not too helpful on a PC but good in small systems.

2) Non portable type conversions. Byte swaps, Accesing the bytes of
larger types.
 
M

mpinto

Imagine you have a particular kind of box, able to store properlly
rice, beans and flour. Posed that those materials have different
physical properties, such as different density, and thre's no meaning
on storing more that one _type_ at a time on the same box (why one need
to filter formerly pure rice from a mix before use it? store it
alone!), if for instance one want to store 1 kg of each material (the
flour supposed to be less dense), the volume of the box must fit at
least the volume ocupied by 1 kg of flour, regardless 1 kg of beans or
rice fits on a smaller box. Remember, the box storage type is multiple,
but one _type_ at a time!.

With unions, you have a box whose size equals the largest size among
the declared ones (as flour for volume), fitting one at a time:

typedef union
{
int int_member;
long long_member;
double double_member;
} cool_union;


typedef struct
{
int int_member;
long long_member;
double double_member;
} cool_struct;

int
main ()
{
cool_union x;
cool_struct y;

return 0;
}

A graphical representation of your memory should rensemble this:
x ->
sizeof (double)
|
.
------------------------------------------------------------------------------------
..
|
|
__________________________________________________
| 0 | 1 | 0 |
.............................................. | 0 | 1 | 0 |
<- binary representation
'
----------------------------------------------------------------------------------------
'
| |
'--------------------------------'
|
'-> sizeof (int)
|
|

'----------------------------------------------------------------------------'
|
'-> sizeof (long)

As you can see, the union overlaps the small types over the largest
one, being able to store any one of those, but one at a time. Besides,
a struct with the same members would reserve space for each one of the
mebers, without the overlap:

sizeof (x) = sizeof (double);
but
sizeof (y) = sizeof (double) + sizeof (long) + sizeof (int).

Concluding, a struct defines a set of boxes, and a union defines a
multipurposed box whose size fits the largest storage type needed to
work.
 
R

regis

typedef union
{
int int_member;
long long_member;
double double_member;
} cool_union;

typedef struct
{
int int_member;
long long_member;
double double_member;
} cool_struct;

cool_union x;
cool_struct y;

sizeof (x) = sizeof (double);
but
sizeof (y) = sizeof (double) + sizeof (long) + sizeof (int).

No, sizeof (y) >= sizeof (double) + sizeof (long) + sizeof (int)
because it may includes internal padding bytes
behind any of the fields, often to meet alignment requirements.

For example, with
* sizeof (double)=8, sizeof(long)=4, sizeof(int)=2
* 2-bytes alignment for int, 4-bytes alignment for long and double,
* alignment of the struct based on the strictest one of its fields
(so that the location of padding is invariant from struct to struct
and the computation of the offsets of the fields do not vary)
* alignment of the end of struct based on the alignment of the struct
(to match contiguity rule of the struct cells in arrays)
* and padding added only alignement purposes, we have:

sizeof (y) = sizeof (double) + sizeof (long) + sizeof (int) + 2
with two padding bytes behind the int field,
(whatever the fields ordering, on this example).

Note that two structs with same fields types and numbers
may have different size according to the ordering of the fields.
E.g., with the rules above and no alignment rule for char,
two structs each with one char, one int, and one long fields,
may either have

sizeof = 8= 1+2+4 + (1 padding byte), or
sizeof = 12= 1+2+4 + (5 padding bytes)

The 8 bytes case happens when ordering field sizes:
- by increasing size: char, (1 padding), int, long
- by decreasing size: long, int, char, (1 padding)

The 12 bytes case happens with nonmonotonic field size ordering,
e.g:

- char, (3 padding), int, (2 padding), long
- int, (2 padding), long, char, (3 padding)
 
R

regis

regis said:
The 8 bytes case happens when ordering field sizes:
- by increasing size: char, (1 padding), int, long
- by decreasing size: long, int, char, (1 padding)

The 12 bytes case happens with nonmonotonic field size ordering,
e.g:

- char, (3 padding), int, (2 padding), long


Oups... the line above should be read:
- char, (3 padding), long, int (2 padding)
 

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

Similar Threads


Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top