I think you are misunderstanding Unions.
The idea behind using unions is toe save memory...
yes, that's one reason
... and get result equivalent to structure...
no
it's not equivalent. They looks similar in source code, but it is a completely different thing. Like apples and airplanes.
Unions are a very, very low level construct that allows you to see a piece of memory as if storing any of its "members", but you only can use one at a time. Even the use of the word "member" is extremely misleading. They should be called "views" or something, not members.
When you write:
union ABCunion
{
int a;
double b;
char c;
} myAbc;
You are saying: "take a piece of memory big enough for the biggest among an int, a char and a double, and lets call it myAbc.
In that memory, now you can store either an int, or a double, or a char. If you store an int, and then store a double, the int is gone forever.
What's the point then?
There are two major uses for Unions.
a) Discriminated storage
That's what we did above. I pick a piece of memory and I give it different meanings depending on context. Sometimes the context is explicit (you keep some variable that indicates what "kind" of variable you stored), and sometimes it can be implicit (based of the section of code, you can tell which one must be in use). Either way, the code needs to be able to figure it out, or you won't be able to do anything sensible with the variable.
A typical (explicit) example would be:
struct MyVariantType
{
int typeIndicator ; // type=1 -> It's an int,
// type=2 -> It's a double,
// type=3 -> It's a char
ABCunion body;
};
For example, VB6's "Variants" are Unions not unlike the above (but more complex).
b) Split representation
This is sometimes useful when you need to be able to see a variable as either a "whole" or as a combination of parts. It's easier to explain with an example:
union DOUBLEBYTE
{
struct
{
unsigned char a;
unsigned char b;
} bytes;
short Integer;
} myVar;
Here's a short int "unioned" with a pair of bytes. Now, you can view the same value as either a short int (myVar.Integer), or you can just as easily study the individual bytes that make part of the value (myVar.bytes.a and myVar.bytes.b).
Note that this second use is not portable (I'm pretty sure); meaning that it's not guaranteed to work across different machine architectures; but this use is absolutely essential for the kind of tasks for which C was designed (OS implementation).