Union In C | Declare, Initialize, Access Member & More (Examples)
Memory management and data representation are critical components of every programming language. In that, the union stands out as a versatile and powerful construct that offers developers a tool for efficient memory management and flexible data representation. In this article, we will discuss all about union in C programming language, its syntax, usage, advantages, applications and common use cases.
Unlike structures, which allocate memory for each member individually, a union in C allows multiple members to share the same memory location. This unique characteristic makes union invaluable for scenarios where a single variable must store different data types at different times.
What Is Union In C?
A union in C programming is a user-defined data type that allows different types of data to be stored in the same memory location. It is similar to a structure but with a key difference, i.e., while structures allocate memory for each member separately, unions allow their members to share the same memory space. This means that a union statement can only hold the value of one of its members at any given time.
Syntax To Define Union In C
union UnionName {
member1_type member1_name;
member2_type member2_name;
// ... additional members ...
};
Here,
- The union keyword indicates that we are declaring a union construct whose name/ identifier is given by UnionName.
- The terms member1_type and member2_type refer to the data types of the members of the union. These can be different data types.
- The identifiers/ names of the union members are member1_name, member2_name, and so on.
Example Of Union Program In C
Let's look at a simple C program that shows how to create a union, initialize its members and print their values.
Code Example:
Output:
Integer value: 42
Float value: 3.140000
Character value: A
Integer value: 1078523201
Code Explanation:
In the C code example, we begin by including the header file for input-output operations, i.e., <stdio.h>.
- We then declare a union named Data, encapsulating three members, i.e., variable i (of integer data type), variable f (float type), and variable c (character type). Unions allocate memory so that all members share the same memory space.
- Inside the main() function, we declare a union variable myUnion of type Data.
- After that, we use the dot operator (.) to initialize the members of myUnion.
- We assign the value 42 to union member i and use a printf() statement to display the same to the console.
- Here, the %d format specifier indicates an integer value, and the newline escape sequence (\n) shifts the cursor to the next line before printing the next output.
- Similarly, we initialize union variables f and c with the values 3.14 and A (using single quotes for string declaration), respectively.
- We also print both the values to the console using the printf() function with appropriate format specifiers.
- Following this, we re-print the value of union variable i using the same method.
- But as mentioned in the multi-line code comment, since union members share the same memory space, accessing another member when the last assigned member was c might lead to undefined behaviour.
- As you can see in the output window, the value of integer member displayed is wrong.
- Finally, the main() function terminates with a return 0 statement, signalling the successful completion of the program.
How To Create Variables Of Union In C?
As we know, a union in C is a user-defined data type that allows us to store multiple types of data in a single location. Each instance of a union is referred to as a union variable, and each piece of data/ element of instance is referred to as a union member. It is important to note that while a union in C stores multiple data types simultaneously, only one member can be active or in use at any given time.
- When creating a union variable, you are essentially declaring a variable of the union type, which reserves memory space for the union and its members.
- You can then access and manipulate the members of the union variable to store and retrieve data.
- For example, consider a union named Shape with members sides, radius, and area, each representing different properties of geometric shapes.
- You can create a union variable named myShape of type Shape and access its members to store and retrieve data about different shapes.
There are two options when you write/ run a C program where we can declare a union variable. The first option is with the union declaration (before main() begins), and the second is inside the main() function after you have declared the union. We will discuss both of these in this section.
Creating Variable Of Union In C With Declaration (Outside Main)
When declaring a union, you define its structure and its members using the union keyword. At the same time, you can declare a variable of that union type, creating an instance of the union. This involves specifying the union's name followed by the variable name. This method allows you to define the union and create a variable of that type in one block.
Syntax:
union UnionName {
member1_type member1_name;
// Additional members, if any
};
union UnionName variableName;
Here, the syntax is similar to that for creation of a union in C. The only addition is that after we have declared the union, we have created an instance right away. For this, we use-
- The union keyword indicates that the instance belongs to a union in C.
- The name of the union whose instance/ variable we are creating is given here by UnionName, and the name you want to give to the union variable, here, variableName.
Let's look at a C program example which shows how this approach to create a union variable is implemented.
Code Example:
Output:
Number of sides: 4
Radius: 3.50
Area: 12.56
Explanation:
In the example C code-
- We declare a union named Shape, which serves as a container for representing different aspects of geometric shapes.
- The Shape union contains three members, i.e., sides (integer type), radius (float type), and area (double type). These members represent the number of sides, the radius of the shape, and the area of a shape, respectively.
- After that, we declare a union variable called myShape of type Shape before the main() function, which will be the program's entry point for execution.
- Moving on, in the main() function, we assign values to each member of the union variable myShape and print them side by side.
- We assign the value 4 to the myShape member sides, indicating a shape with four sides. We then use a printf() statement to display this to the console along with the string message.
- Similarly, we assign values 3.5 and 12.56 to myShape union members radius and area (respectively), indicating the radius of a circle and area of the shape. We print both these values to the console right after initialization.
- As mentioned in the code comment, if we initialize all members first and then print them together, it will lead to undefined behaviour.
- This is because all members share the same memory space and the last initialized member remains active at the time of printing the values.
- Finally, we return 0 from the main() function to indicate successful completion.
Creating Variable Of Union In C Inside Main
We can also create/ declare a union variable inside the main() function after declaring a union, that is, separate from the declaration. This involves declaring a variable of the union type using the union's name, followed by accessing and modifying its members using the dot (.) operator. This method allows for more flexibility as you can declare variables of the union type at different points in your code.
Syntax:
union UnionName {
// member_types and member_names
};int main() {
union UnionName variableName; // Union Variable Declaration
Here, the only deviation from the syntax of creating a variable with declaration is that we have declared the variable of union in C inside the main() function. Look at the example C program given below to understand this method.
Code Example:
Output:
Number of sides: 4
Radius: 3.50
Explanation:
In the sample C code-
- We first declare a union named Shape with three union members, just like the previous example.
- But instead of declaring a union variable right after the union declaration, we move to the main() function.
- Inside the main() function, we declare the union variable myShape of type Shape. (The syntax for the declaration of the variable remains the same).
- Then, we initialize two members of the union variable myShape using the dot operator (.) and print them side by side. (Just like in the previous example.)
- The %.2f format specifier inside the printf() statement helps display the value with two decimal places.
How To Initialize The Members Of Union In C?
Initialization of the union variable involves setting initial values for its members, each representing different data types, within the union's memory space.
- However, due to the nature of unions, only one member can be actively initialized at any given time.
- This means that initializing one member may overwrite the values of previously initialized members.
- To initialize a union, you declare an instance of the union, select the member you want to initialize and assign it an initial value compatible with its data type.
- After initialization, you can access and use the initialized member in your program.
It's important to ensure that the appropriate member is initialized before accessing its value to avoid undefined behaviour.
Syntax for Initialization of Members of a Union in C:
var1.member1 = value;
Here,
- The term var1 refers to the union variable whose members we are initializing.
- And member1 is the identifier of the respective union member we are initializing.
- The dot operator (.) helps access the respective union member, and the value refers to the initial value we are assigning to the member.
We have used this method in all the previous examples. Another alternative way of initializing union members of a union variable is along with the declaration inside the main() function.
Syntax for Initializing Member with Variable Declaration:
union unionName variableName = { .memberName = value};
However, it is important to note that if you initialize more than one member through this method and then print the values, only the last active members will be printed right and the other will take garbage values. Take a look at the sample C program below to understand how to initialize the union members and access them using the dot operator.
Code Example:
Output:
Age: 25
Code Explanation:
In the C code sample-
- We define a union named Person with three union members: age (integer), height (floating-point number), and gender (char data type).
- In the main() function, we declare a union variable named person of type Person and simultaneously initialize its member age with the value 25.
- Then, we use a printf() statement to display this value.
- Now look at the comment that contains code to initialize more than one member in a single go and then print them. As mentioned, this will lead to undefined behaviour when we try to access the age variable since the last active member is height.
Memory Allocation For Union In C
When a union is created in C, memory allocation occurs to reserve space for the union in the program's memory. Here's how memory allocation works for a union in C programs:
Step 1- Size Determination: The size of a union in C is determined by the size of its largest member.
- This ensures that the union has enough memory to accommodate any of its member types without data loss or corruption.
- That is, the compiler analyzes the members of the union in C and identifies the largest member among them. The size of the union is set equal to the size of its largest member.
Step 2- Memory Reservation: Once the size of the union is determined, the compiler reserves memory space accordingly. The memory reserved for the union is contiguous, meaning it is allocated as a single block of memory.
Step 3- Alignment Requirements: The compiler may add padding bytes to ensure that the alignment requirements of the union are met.
- Alignment refers to the memory addresses at which data is stored. Certain data types have alignment requirements, and the compiler ensures that these requirements are satisfied to optimize memory access and performance.
- The padding ensures that each member of the union in C is properly aligned within the memory space allocated for the union.
Step 4- Memory Addressing: The memory address of a union in C is typically the address of its first member. Since all members of a union share the same memory space, accessing any member of the union retrieves the data stored in that portion of memory.
Step 5- Accessing Members: Members of a union in C can be accessed using the dot (.) operator followed by the member's name.
- When accessing a member of a union, the compiler ensures that the correct portion of memory corresponding to that member is accessed.
- It's important to note that only one member of a union can be active or in use at any given time. Writing to one member of the union may overwrite the data stored in other members.
All in all, the memory allocation for a union in C involves determining the size of the union based on its largest member, reserving contiguous memory space, ensuring alignment requirements are met, and allowing access to individual members using the appropriate syntax. This process ensures efficient utilization of memory while providing flexibility in representing different types of data within the same memory space.
How To Access Members Of Union In C?
When you define a union, you're essentially creating a container for multiple members, each of which can have a different data type. These members share the same memory space that you can use to store any of the union's members interchangeably. But you can actively access only one of the members. There are two methods of accessing members of a union in C-
- Using the dot operator (.)
- Using the arrow operator/ 'this' pointer (->)
However, note that accessing members of a union in C programs involves working with a specific/ distinct type of data. The most commonly used member types are:
- Integer Members: These members store whole numbers (integer type).
- Floating-Point Members: These members store decimal numbers (floats or doubles).
- Character Members: These members store individual characters.
- Array Members: These members store collections of elements of the same data type.
- Pointer Members: These members store memory addresses, pointing to specific locations in memory.
We can use the dot operator to access most normal data types of union members values, including integer, double, character, string (character array) and floating-point values. But when working with pointer type members/ union variables, we must use the arrow pointer method. Let's look at both methods!
Accessing Normal Members Of Union In C Using Dot Operator
Accessing normal members of a union in C using the dot operator (.) is straightforward and is used when the union variable itself is not a pointer. All you have to do is use the dot operator (.) followed by the member name to access and manipulate the members of the union.
Syntax:
variableName.member_name;
Here, we specify the name of the union variable (variableName) and the name of the union member (member_name), connected with a dot operator. We have already seen how to use this approach in the example above, but here is another sample C program demonstrating how to access members of a union in C using the dot operator:
Code Example:
Output:
Number of sides: 5
Explanation:
In the simple C code-
- We define a union named Shape with two members: sides and radius.
- Inside the main() function, we declare a union variable named myShape, which will store values for different shape properties.
- We then assign a value to the sides member of the union using the dot operator (.), since myShape is not a pointer but a direct instance of the union.
Accessing Members of Union In C Using Arrow Pointer
Accessing members of a union in C with the arrow pointer (->) is used when the union variable is a pointer. It involves first declaring a pointer variable of the union type and then using the arrow operator to access and manipulate its members. The arrow pointer dereferences the pointer and accesses the member directly.
Syntax:
//Declaring a pointer type union variable
union UnionName *ptrVariable;// Accessing member using arrow operator
ptrVariable->member1_name;
Here, the syntax for declaring a union variable will also change since it is of pointer type. So, we first declare a pointer type union variable. Then, use the arrow operator (->) followed by the member name to access and manipulate it.
- The unary operator (*) in variable declaration indicates that the union variable with the name ptrVariable is of pointer type.
- The arrow (->) operator in the next line helps access the member with the name member_name.
Here's a code example demonstrating how to access members of a union in C using the arrow pointer.
Code Example:
Output:
Number of sides: 4
Explanation:
In the C code-
- We define a union named Shape with two members: sides and radius, which represent properties of geometric shapes.
- Inside the main() function, we declare a pointer type union variable named ptrShape.
- Then, we dynamically allocate memory for the union variable using the malloc() function and sizeof() operator to determine the union size.
- Once the memory is allocated, we use the arrow pointer (-->) to access the side member of the ptrShape union variable and assign a value 4 to it.
- Next, we print the value of the side variable to the console using the printf() function.
- After that, we free the allocated memory using the free() function to avoid memory leaks.
- Finally, the main() function closes with a return 0.
Structures Inside Union In C
A union in C provide a way to conserve memory allocated to a variable by allowing multiple different data types to share the same memory location. However, one primary limitation of unions is that we can only access the active member at a given time. We can overcome this limitation to a certain degree and enhance the versatility of unions by leveraging structures inside of a union in C programs.
- By embedding structures inside unions, we can create union members that consist of multiple data fields, each with its own data type.
- This approach enables us to organize and access multiple pieces of information within the same memory location, offering greater flexibility and efficiency in handling diverse data structures.
Below is an example that shows how we can nest structures inside a union in C and then access multiple members of the structure at any time.
Code Example:
Output:
Shape: Circle
Radius: 5.00Shape: Rectangle
Width: 4.00
Height: 6.00
Explanation:
In the C code-
- We define a union named Shape, which can hold two shapes, i.e., a Circle or a Rectangle.
- Inside the union, we define two structure members (using the struct keyword), i.e., Circle and Rectangle, each representing a specific shape.
- The Circle structure contains a single member- radius, representing the radius of the circle.
- The Rectangle struct contains two integer type members, i.e., width and height, representing the width and height of the rectangle, respectively.
- In the main() function, we declare an instance of the Shape union named myShape.
- Then, we initialize the radius member of the circle variable within myShape to 5.0 using the dot operator, i.e., myShape.circle.radius
- Note that here, the dot operator appears twice, once after the union name, then between the variable name (i.e., circle) and the member name (i.e., radius).
- After that, we use printf() to access and display the value of the radius member.
- Next, we declare another instance of the Shape union named myRectangle.
- Once again, we initialize the width and height members of the rectangle variable within myRectangle to 4.0 and 6.0, respectively.
- Following this, we access and print the values of these members to the console. This does not generate undefined behaviour.
How Does The Compiler Define The Size Of Union In C?
As mentioned before, the size of a union in C is determined by the size of its largest member to allocate memory that is large enough to accommodate its largest member without overflow.
Here's a step-by-step process of how a compiler defines the size of a union:
- Compilation Stage: When the compiler encounters a union declaration, it analyzes the members of the union to determine their sizes and alignment requirements.
- Size Calculation: The compiler calculates the size of each member of the union in C based on its data type and zeroes in on the largest member.
- Memory Allocation: The compiler allocates memory for the union in C such that it is large enough to hold the largest member without data loss or corruption.
- Padding: The compiler may add padding bytes to meet the alignment requirements of the union in C. This ensures that each member is properly aligned in memory to facilitate efficient memory access and improve performance.
- Size Determination: Finally, the compiler determines the size of the union by considering the size of its largest member along with any padding bytes.
Below is a simple C code example where we see how to check/ determine the size of a union variable, i.e., union size.
Code Example:
Output:
Size of union: 8 bytes
Explanation:
In this code, we first declare a union SampleUnion with three members, i.e., int, double, and char. Next, we create a union variable called myUnion and use the sizeof() operator to calculate its size. The sizeof operator gives the size in bytes of its operand, which in this case is myUnion.
Applications/ Need Of Union In C
A union in C is a versatile construct with various applications in programming. Some common reasons why we need to use the union in C are:
- Memory Optimization: Unions are frequently used to optimize memory usage when dealing with different data types that share the same memory space. For example, in embedded systems or low-level programming, where memory constraints are critical, unions enable efficient utilization of memory by allowing multiple types to occupy the same memory location.
- Variant Data Structures: A union in C is valuable for creating variant data structures, where a single data structure can represent different types of data at different times. For example, when parsing binary data formats or implementing polymorphic data structures like variant records.
- Type Puning: Unions in C are often used for type punning, a technique where the same memory location is interpreted as different data types at different times. This can be useful for low-level manipulation of data, such as converting between different numeric representations or interpreting raw memory buffers in different ways.
- Interfacing with Hardware: Unions are commonly employed when interfacing with hardware devices or external systems that require sending or receiving data in various formats. Developers can use a union in C programs to define a single data structure that accommodates different data representations required by the hardware, simplifying communication protocols and device drivers.
- Union-Find Data Structure: Unions are integral to implementing the union-find data structure, which is used in graph algorithms and disjoint-set data structures. In union-find, unions are performed to merge two sets, and efficient algorithms leverage unions to track connectivity and partition union elements into disjoint sets.
- Bit Manipulation: Bitwise operations are more efficient when you overlay a union in C programs with a bitfield and other data types. They can, hence, be used for bit manipulation and bitwise operations, particularly when dealing with packed data structures or manipulating individual bits within a larger data structure.
- Platform-Dependent Data Representation: Unions are useful for dealing with platform-dependent data representations, where the layout and size of data types may vary across different systems. By defining unions with platform-specific representations, developers can ensure compatibility and portability of their code across different architectures.
- Passing Parameter to Functions: Unions can be used to efficiently pass parameters to functions, especially when the function needs to accept different types of data. By using a union parameter, the function can handle multiple types of data without the need for overloaded functions or complicated type checking.
- Compact Data Representation: Unions enable the creation of compact data representations by overlaying different types of data in the same memory space. This is useful when storing and transmitting data in a compact format, such as in communication protocols or file formats.
Advantages & Disadvantages of Union In C
Unions in C offer unique advantages and disadvantages compared to other data structures like structures. Here's a breakdown:
Advantage Of Union In C:
- Efficient Memory Allocation: A union in C allows you to conserve memory by enabling different data types to share the same memory location. And since only one union member is active at any given time, the memory allocated is only as large as the largest member.
- Versatility: Union in C provides flexibility in handling different types of data using the same memory space. This versatility is particularly useful in scenarios where memory optimization is crucial or when dealing with data of varying types that share a common memory.
- Compactness: You can create a more compact data structure by using union in C programs to overlay different data types in the same memory. This is especially useful when dealing with limited memory environments or optimising memory usage.
- Efficient Parameter Passing: A union in C is also useful for passing parameters to functions efficiently. They allow you to pass a single parameter representing different data types, thus reducing the complexity of function signatures and improving code readability.
Disadvantages Of Union In C:
- Type Safety: A union in C lacks the type safety provided by structures, since it allows multiple types to share the same memory space. Accessing the wrong member or misinterpreting the data type can lead to runtime errors or unexpected behaviour.
- Undefined Behavior: Accessing an inactive union member in C can lead to undefined behaviour. The data retrieved may not be meaningful or valid, potentially resulting in bugs that are difficult to diagnose.
- Readability and Maintenance: If used improperly, a union in C can make code less readable and harder to maintain. It can also lead to potential errors and inconsistency if the developers do not understand the intended use of a union.
- Debugging Complexity: The potential for undefined behaviour and data representations can make it difficult to debug a code containing unions. Identifying issues related to incorrect member access or data interpretation may require thorough inspection and testing.
Overall, while a union in C offers benefits in terms of memory efficiency and versatility, it also comes with trade-offs regarding type safety, readability, and debugging complexity.
Differences Between Structure & Union In C
Structures and unions in C have several differences that distinguish their usage and behaviour. This includes:
Memory Allocation to Members:
- Structures: Each member occupies its own separate memory space, resulting in a size equal to the sum of the sizes of all its members. This means that a structure holds all its members simultaneously, allowing access to each member individually.
- Union in C: Memory is allocated to accommodate the largest member, but only one member can be active or used at any given time. This means that the union data type provides a way to overlay different data in the same memory space. It promotes efficient memory use when only one member needs to be accessed or modified at a time.
Initialization & Usage:
- Structures are typically used to represent complex data structures where all members are relevant simultaneously.
- Union in C is often used when different interpretations or representations of the same memory space are needed, such as when handling various types of data in a compact manner.
Type Safety & Code Clarity:
- Structures offer better type safety and clarity in code due to their explicit declaration of multiple members.
- Union in C require careful handling to ensure that the correct member is accessed or modified at any given time.
Similarities Between Structure and Union In C
Structures and unions are both fundamental constructs in programming languages like C . While they serve different purposes, they share some similarities as follows:
Basis |
Similarities |
|
Composite Data Types |
Both are composite data types that allow use to group variables together. |
|
Member Access |
We can access the members of a structure and a union in C using the dot operator (.) followed by the member name. |
|
Data Organization |
Used to organize related data elements, where one is structured, and the other allows memory-sharing. |
|
Code Clarity |
Enhances code readability and clarity by grouping related variables. (However, union in C also allows memory sharing.) |
|
Function Parameters |
They can be used as function parameters to pass multiple values. |
|
Syntax |
The syntax for defining members and creating instances is similar. (However, the keywords used are different.) |
Conclusion
A union in C is a powerful construct that allows us to handle different types of data by storing them in the same memory space, and it promotes efficient memory management. They allow developers to define a composite data type that can hold members of different data types simultaneously. By sharing the same memory location for all members, unions enable memory optimization and flexibility in data representation.
The creation of a union variable is similar to that of an object in a class. We can access the members of a union variable using a dot operator (for normal types) and an arrow operator (for pointer type variables). There are many benefits of using a union in C, such as efficient memory allocation and management, improved code readability, compactness, versatility and more. However, we must also be cautious of the cons of using union in C, i.e., lack of type safety, inability to access multiple members simultaneously, etc.
Frequently Asked Questions
Q. Can we store data in multiple union members at the same time?
No, you can only store data in one member of a union at one point in time. The memory allocated for a union in C is shared among its members, and only the active member holds valid data. Storing data in one member will overwrite the data in another member if it was previously stored. This is a key characteristic of unions, i.e., they allow you to switch between different data types, but you can't hold data in multiple members simultaneously.
Q. What are some common use cases for unions in C?
Unions are commonly used in scenarios where a single variable must hold different data types at different times. For example, a union in C can represent variant data types, such as a variable with an integer, a floating-point number, or a character value. They are also useful in implementing polymorphism, where different types of objects can be stored in the same variable.
Q. How to ensure safe and correct usage of union in C?
It's essential to ensure that the correct member of a union is being accessed and manipulated at any given time.
- Failure to do so may lead to undefined behaviour and data corruption.
- Proper documentation and clear naming conventions for union members can help prevent errors.
- Additionally, using unions judiciously and understanding their limitations can help avoid potential pitfalls.
Q. How is memory allocated for a union in C, and what factors determine the size of a union?
In C, memory allocation for a union follows some key principles. When a union is declared, memory is allocated based on the size of its largest member. This ensures that the union can accommodate the largest possible data type among its members.
Factors determining the size of a union include:
- Size of the Largest Member: The size of the union is determined by the size of its largest member. This ensures that the union has enough memory to hold any member with any chunk of memory.
- Alignment Requirements: Memory alignment rules in C may affect the size of the union. For example, if the largest memory requires stricter alignment than a smaller one, padding may be added to align the larger member properly.
- Padding and Alignment of Members: Depending on the data types and their alignments, the compiler may insert padding bytes between members to ensure proper alignment. This padding contributes to the overall size of the union.
It's essential to note that all members of a union share the same memory location. Therefore, the size of the union is determined by the size of its largest member to accommodate any possible member that may be active at runtime. This memory-sharing property allows different types of data to be stored in the same memory location, improving memory efficiency.
Q. What are some limitations of union in C?
A primary limitation of using a union in C programming is that only one of its members can be active or in use at any given time. This means that accessing one member may overwrite the values of other members. Additionally, the lack of type safety (that is present in structures) can lead to undefined behaviour and corruption if we access a member that is not active. This means we must ensure that we are accessing and manipulating the correct member of a union in C.
Here are a few more topics that you must explore:
- 6 Relational Operators In C & Precedence Explained (+Examples)
- Decimal To Binary In C | 11 Methods (Examples + Complexity Analysis)
- Reverse A String In C | 10 Different Ways With Detailed Examples
- Operators In C Programming: Explained With Examples
- Tokens In C | A Complete Guide To 7 Token Types (With Examples)