Home | Projects | Notes > C Programming > Unions
A union in C is similar to a structure except that all of its members start at the same location in memory.
A union variable can represent the value of only one of its members at a time.
Use union instead of structure to save memory when the access to its member elements is mutually exclusive.
For example, when sending a packet from a transmitter to a receiver you either use the long address or the short address but not both at the same time. In other words, using the long address and the short address are mutually exclusive.
xxxxxxxxxx
61/* memory efficient - preferred */
2union address
3{
4 uint16_t shortAddr;
5 uint32_t longAddr;
6};
xxxxxxxxxx
61/* memory inefficient - not preferred */
2struct address
3{
4 uint16_t shortAddr;
5 uint32_t longAddr;
6};
Following program demonstrates the way unions work.
xxxxxxxxxx
211
2
3
4union address
5{
6 uint16_t shortAddr;
7 uint32_t longAddr;
8}
9
10int main(int argc, char *argv[])
11{
12 union Address addr;
13
14 addr.shortAddr = 0xABCD;
15 addr.longAddr = 0xEEEECCCC; /* overwrites the previous assignment */
16
17 printf("shortAddr = %#x\n", addr.shortAddr);
18 printf("longAddr = %#x\n", addr.longAddr);
19
20 return 0;
21}
xxxxxxxxxx
21shortAddr = 0XCCCC
2longAddr = 0XEEEECCCC
Benefits:
Bit extraction
Storing mutually exclusive data thus saving memory
Following program demonstrates how union & structure combination can be used to save memory and make the bit extraction very easy.
xxxxxxxxxx
521
2
3
4union Packet
5{
6 uint32_t packetInfo;
7
8 struct
9 {
10 uint32_t crc :2;
11 uint32_t status :1;
12 uint32_t payload :12;
13 uint32_t bat :3;
14 uint32_t sensor :3;
15 uint32_t longAddr :8;
16 uint32_t shortAddr :2;
17 uint32_t addrMode :1;
18 } PacketFields; /* now PacketFields act as a member struct variable name */
19};
20
21int main(int argc, char *argv[])
22{
23 union Packet packet;
24 uint32_t packetInfo;
25
26 printf("Enter 32-bit packet information (in hex): "); /* 0xFFFFFFFF or FFFFFFFF */
27 scanf("%x", &packet.packetInfo);
28
29 /* now the following code is no longer necessary
30 packet.crc = (uint8_t)(packetInfo & 0x3);
31 packet.status = (uint8_t)((packetInfo >> 2) & 0x1);
32 packet.payload = (uint16_t)((packetInfo >> 3) & 0xFFF);
33 packet.bat = (uint8_t)((packetInfo >> 15) & 0x7);
34 packet.sensor = (uint8_t)((packetInfo >> 18) & 0x7);
35 packet.longAddr = (uint8_t)((packetInfo >> 21) & 0xFF);
36 packet.shortAddr = (uint8_t)((packetInfo >> 29) & 0x3);
37 packet.addrMode = (uint8_t)((packetInfo >> 31) & 0x1);
38 */
39
40 printf("crc : %#x\n", packet.PacketFields.crc);
41 printf("status : %#x\n", packet.PacketFields.status);
42 printf("payload : %#x\n", packet.PacketFields.payload);
43 printf("bat : %#x\n", packet.PacketFields.bat);
44 printf("sensor : %#x\n", packet.PacketFields.sensor);
45 printf("longAddr : %#x\n", packet.PacketFields.longAddr);
46 printf("shortAddr : %#x\n", packet.PacketFields.shortAddr);
47 printf("addrMode : %#x\n", packet.PacketFields.addrMode);
48
49 printf("Size of packet (struct) is %lu bytes.\n", sizeof(packet)); /* %I64u */
50
51 return 0;
52}
xxxxxxxxxx
101Enter 32-bit packet information (in hex): 0xFFFFFFFF
2crc : 0x3
3status : 0x1
4payload : 0xfff
5bat : 0x7
6sensor : 0x7
7longAddr : 0xff
8shortAddr : 0x3
9addrMode : 0x1
10Size of packet (struct) is 4 bytes.
Nayak, K. (2022). Microcontroller Embedded C Programming: Absolute Beginners [Video file]. Retrieved from https://www.udemy.com/course/microcontroller-embedded-c-programming/