- Overview
- Defining a union
- Anonymous unions
- Unions with typedef
- Accessing union members
- Union initialisation
- Printing union members
- External References
- Stores different types of data in the same storage area.
- Saves on space for alternating data types.
- Size determined by the largest type.
The declaration is identical to that of a struct, except the keyword union is used.
union union_tag { // union_tag optional
type1 identifier_1;
type2 identifier_2;
} optional_variable_definitions;The union definition is placed in the header and included in all source files that use the union type.
Example
union Data {
int i; // 4 bytes
float f; // 8 bytes
char str[20]; // 20 bytes
} data1, data2; //global union variables optionalA variable of type Data, can store an integer or a float, or a string of chars, not all. A struct could store all but not a union.
The memory occupied by a union will be large enough to hold the largest member, in this case 20 bytes as char str[20] is the largest member.
- No memory is allocated until variables are created.
- There is no limit to the number of members.
- Struct can contain unions, as can arrays.
- Pointers to unions work the same as with structs.
Example
#include <stdio.h>
union Car {
int i_value; // 4 bytes
float f_value; // 4 bytes
char c_value[40]; // 40 bytes largest member
}; //car1, car2, *car3; // can declare here
int main()
{
union Car car1, car2, *car3; // declare unions
printf("Size of union: %zu bytes.\n", sizeof(car1));
return 0;
}Output
Size of union: 40 bytes.The example code below, shows how the union memory storage is changed when assigning different type to the members.
#include <stdio.h>
#include <string.h>
union sample {
int i;
char ca[4];
float f;
};
int main()
{
union sample u;
u.i = 42;
printf("%08x %f %s\n", u.i, u.f, u.ca);
strcpy(u.ca, "Abc"); // copy 3 chars leaving space for null operator
printf("%08x %f %s\n", u.i, u.f, u.ca);
u.f = 1.0/3.0;
printf("%08x %f %s\n", u.i, u.f, u.ca);
return 0;
}Output
0000002a 0.000000 * // 2a hex is 42
00636241 0.000000 Abc // 00 is null operator, 63 is `A`, 62 is `b`, 41 is 'c'.
3eaaaaab 0.333333 □□□>0□□□ // 32aaaaab is 0.3333 in hexIntroduced in C11. Anonymous unions exist only inside another union or struct. It has no union tag or variables assigned to it.
Example
#include <stdio.h>
struct Owner{
char socsecurity[12];
};
struct Lease_company{
char name[40];
char headquarters[40];
};
struct Car_data {
char make[15];
int status;
union { // Anonymous union
struct Owner own_car;
struct Lease_company lease_car;
};
};
int main()
{
...struct {
char* name;
enum symbolType type;
union {
int i;
float f;
char c;
}; data; // union variable
} table [entries]; // array named tableAs with a struct a typedef can be declared for a union. This is not best practice as the word union is good information for the reader of your code.
typedef union {
int x;
float y;
char z;
} myunion;
int main(){
myunion u; // no need for union keyword
u.x = 99;
u.y = 1.0;
u.z = 'c';
...
}We access/assign data to members of a union, the same was we do with a struct:
- with the (.) dot operator to access members
- with the (->) indirection operator to access pointer variables
Union member assignment example
#include <stdio.h>
union {
int code;
float cost;
} item; // global variable
int main()
{
item.code = 1234;
return 0;
}Accessing pointer members example
#include <stdio.h>
union {
int code;
float cost;
} item, *ptrst;
int main()
{
ptrst = &item;
ptrst->code = 9876; // assigns an int to code member
return 0;
}The following expressions are equivalents
- ptrst->code = 9876; // preferred method
- item.code = 9876;
- (*ptrst).code = 9876;
#include <stdio.h>
union mixed {
char c;
float f;
int i;
};
int main()
{
union mixed x; // can store one only at a time of the three members
x.c = 'q';
printf("Char at c: %c\n", x.c); // prints, Char at c: q
x.f = 3.142; // union memory overwritten with 3.142
printf("Float at f: %f\n", x.f); // prints, Float at f: 3.142000
x.i = 1234 / 2; // union memory overwritten with 617
printf("Int at i: %d\n", x.i); // prints, Int at i: 617
return 0;
}As with a struct there are a few ways to initialise a union.
#include <stdio.h>
union Number {
int x;
double y;
};
int main()
{
union Number value1 = {12}; // int is first member in union, so needs a int
// preferred alternatives
union Number value2 = {.x = 12};
union Number value3 = {.y = 3.142};
union Number value4;
value4.x = 12;
union Number value5;
value5.y = 3.142;
return 0;
}Using pointers example
#include <stdio.h>
union Number {
int x;
double y;
};
int main()
{
union Number value1;
union Number *value2 = &value1;
value2->y = 10.0;
printf("Double at value2 y: %f\n", value2->y);
return 0;
}Using functions example
#include <stdio.h>
union Number {
int x;
double y;
};
// Initialise another union of Number via function foo
void foo(union Number n){
union Number value2 = n;
printf("Double at value2 y: %f\n", value2.y);
}
int main()
{
union Number value1 = {.y = 12.2};
printf("Double at value1 y: %f\n", value1.y);
foo(value1); // initialise another union with a union via a function
return 0;
}Here is a program that uses a struct and a anonymous union. The struct represents a Spaceship and the union represents a upgrade speed multiplier.
#include <stdio.h>
#include <stdbool.h>
struct Spaceship {
char* name;
bool upgrade;
char upgradeClass;
float speed;
union {
float aClassUpgrade;
float sClassUpgrade;
};
};
void print_stats(struct Spaceship* c){
printf("Name: %s: ", c->name);
if (c->upgrade){
if (c->upgradeClass == 's')
printf("speed %f", c->speed * c->sClassUpgrade);
else
printf("speed %f", c->speed * c->aClassUpgrade);
} else {
printf("speed %f", c->speed);
}
printf("\n");
}
int main()
{
struct Spaceship cruiserX;
cruiserX.name = "Cruiser X";
cruiserX.speed = 23.0;
cruiserX.upgrade = true;
cruiserX.upgradeClass = 's';
cruiserX.sClassUpgrade = 2.5;
print_stats(&cruiserX);
struct Spaceship traderY;
traderY.name = "Trader Y";
traderY.speed = 12.0;
traderY.upgrade = true;
traderY.upgradeClass = 'a';
traderY.aClassUpgrade = 1.1;
print_stats(&traderY);
return 0;
}Output
Name: Cruiser X: speed 57.500000
Name: Trader Y: speed 13.200001