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.
xxxxxxxxxx61/* memory efficient - preferred */2union address3{4 uint16_t shortAddr;5 uint32_t longAddr;6};xxxxxxxxxx61/* memory inefficient - not preferred */2struct address3{4 uint16_t shortAddr;5 uint32_t longAddr; 6};
Following program demonstrates the way unions work.
xxxxxxxxxx21123
4union address5{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}xxxxxxxxxx21shortAddr = 0XCCCC2longAddr = 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.
xxxxxxxxxx52123
4union Packet5{6 uint32_t packetInfo;7 8 struct9 {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 necessary30 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}xxxxxxxxxx101Enter 32-bit packet information (in hex): 0xFFFFFFFF2crc : 0x33status : 0x14payload : 0xfff5bat : 0x76sensor : 0x77longAddr : 0xff8shortAddr : 0x39addrMode : 0x110Size 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/