I am working on optimization of a project. It contains a struct of an options in which user can select a single option at a time. In addition to the option, we also use a flag variable to check which option value is set for this record. In order to make it memory efficient I want to convert struct into a union. But How do I know that which variable value is set in union. Because there is no restriction in union to fetch a value of a variable even which is not set.
struct options{
int basicPay;
int lumsumPay;
int mothlyPay;
int weeklyPay;
int dailyPay;
int anualPay;
int payType; // Flag variable to check which option is selected
};
union OptimizeOptions{
int basicPay;
int lumsumPay;
int mothlyPay;
int weeklyPay;
int dailyPay;
int anualPay;
int payType; // Confuse at here
};
There is no way to tell. You should have some additional flags (or other means external to your union) saying which of the union parts is really used.
In contrast with a record (or structure), which could be defined to contain a float and an integer; in a union, there is only one value at any given time. A union can be pictured as a chunk of memory that is used to store variables of different data types.
The size of a union is sufficient to contain the largest of its data members. Each data member is allocated as if it were the sole member of a struct. That means each member share the same memory region.
Defining a Union It means a single variable, i.e., same memory location, can be used to store multiple types of data. You can use any built-in or user defined data types inside a union based on your requirement.
Unions suffers from a problem that there is no easy way to know which member of a union was last changed. In order to keep track of this information, you can embed union
inside a structure that has one another member (called "tag field" or "discriminant"). The purpose of tag field is to remind which member is changed/updated. You can try this:
typedef struct{
int payType; // Tag field
union{
int basicPay;
int lumsumPay;
int mothlyPay;
int weeklyPay;
int dailyPay;
int anualPay;
}OptimizeOptions;
}Options;
But, there is no need to write six separate members for union in your case as all are of int
type. Therefore it can be reduced to
typedef struct{
enum{BASIC_PAY, LUMSUM_PAY, MONTHLU_PAY, WEEKLY_PAY, DAILY_PAY, ANNUAL_PAY} payType;
int pay;
}Options;
Lets understand the use of tag field with a simple example. Suppose we want an array which can store int
and double
type data. This would become possible by using union
. So, first define a union type which will store either int
or double
.
typedef union {
int i;
double d;
} Num;
Next we have to create an array whose elements are Num
type
Num num_arr[100];
Now, suppose we want to assign element 0
of the num_arr
to store 25
, while element 1
stores 3.147
. This can be done as
num_arr[0].i = 25;
num_arr[1].d = 3.147;
Now suppose that we have to write a function which will print the num_arr
elements. The function would be like this:
void print_num(Num n)
{
if(n contains integer)
printf("%d", n.i);
else
printf("%f", n.d);
}
Wait! How could print_num
will decide whether n
contains an integer or double
?
This will be done by using the tag field:
typedef struct{
enum{INT, DOUBLE} kind; //Tag field
union{
int i;
double d;
}u;
}Num;
So, each time a value is assigned to a member of u
, kind
must1 be set to either INT
or DOUBLE
to remind that what type we actually stored. For example:
n.u.i = 100;
n.kind = INT;
The print_num
function would be like this:
void print_num(Num n)
{
if(n.kind == INT)
printf("%d", n.i);
else
printf("%f", n.d);
}
1: It is programmer's responsibility to update the tag field with each assignment to the member of union
. Forgetting to do so will lead to bug, as pointed in comment by @ j_random_hacker.
Have you tried a union
inside of a struct
? Let’s see the following example equivalent:
union options{
int basicPay;
int lumsumPay;
int mothlyPay;
int weeklyPay;
int dailyPay;
int anualPay;
};
struct record{
union options op; // Options union
int payType; // Flag variable to check which option is selected
}
The union (options
) will reserve memory for its largest variable and you can set its value and your structure (record) will keep track of that union memory block and the payType
flag value could be set which will tell your program to fetch the perticular variable of the union.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With