Lesson 19
Structures and Unions
Structures (struct) and unions (union) are user-defined data types in C that allow you to group multiple variables of different data types under a single name. A structure allocates separate memory for each member, while a union shares the same memory location among all its members.
C Track
Save progress as you learn.
44 lessons
Lesson content
Structures and Unions in C Programming: A Complete Beginner to Advanced Guide
What are Structures and Unions in C Programming?
Structures (struct) and unions (union) are user-defined data types in C that allow you to group multiple variables of different data types under a single name.
While both can store different types of data together, they differ in how memory is allocated: a structure allocates separate memory for each member, while a union shares the same memory location among all its members.
Think of a structure as a toolbox with separate compartments, where each tool has its own space. A union, on the other hand, is like one compartment that can hold only one tool at a time.
Why Do Structures and Unions Exist?
In real-world programs, related information often belongs together. For example, a student has a name, roll number, and marks. Instead of managing these as separate variables, structures and unions let you organize them into a single entity.
They help to:
- Group related data
- Improve code organization
- Simplify data management
- Save memory (using unions)
- Model real-world objects
Real-World Use Cases
Structures and unions are widely used in:
- Student and employee management systems
- Banking applications
- Inventory systems
- File handling
- Graphics programming
- Network packet processing
- Embedded systems
- Operating systems
Prerequisites
Before learning Structures and Unions in C Programming, you should understand:
- Variables and data types
- Arrays
- Functions
- Pointers (recommended)
- Input and output functions
Core Concepts of Structures and Unions in C Programming
What is a Structure?
A structure is a user-defined data type that groups variables of different data types into a single unit.
Syntax
struct StructureName
{
dataType member1;
dataType member2;
dataType member3;
};Example
struct Student
{
int rollNo;
char name[50];
float marks;
};Declaring Structure Variables
struct Student student1;Or multiple variables:
struct Student student1, student2;Accessing Structure Members
Use the dot (.) operator.
student1.rollNo = 101;What is a Union?
A union is also a user-defined data type, but all its members share the same memory location.
Syntax
union UnionName
{
dataType member1;
dataType member2;
};Example
union Data
{
int number;
float decimal;
char letter;
};Only one member contains a meaningful value at any given time because writing to one member overwrites the others.
Memory Difference
Structure: each member gets separate memory (rollNo, name, and marks each occupy their own space). Total size is approximately the sum of member sizes, plus possible padding for alignment.
Union: all members share the same memory. Total size equals the size of the largest member, plus alignment requirements.
Initializing Structures
struct Student student = {101, "Alice", 95.5};Initializing Unions
union Data value = {.number = 100};Nested Structures
A structure can contain another structure.
struct Address
{
char city[30];
};
struct Student
{
char name[30];
struct Address address;
};Access nested members using:
student.address.cityArray of Structures
struct Student students[3];Useful for storing records.
Pointer to Structure
Use the arrow (->) operator.
struct Student student;
struct Student *ptr = &student;
ptr->rollNo = 10;Structure vs Union
| Feature | Structure | Union |
|---|---|---|
| Memory Allocation | Separate for each member | Shared among all members |
| Size | Sum of member sizes (plus padding) | Size of the largest member (plus alignment) |
| Members | All members can store values simultaneously | Only one member is valid at a time |
| Memory Efficiency | Lower | Higher |
| Use Case | Store complete records | Save memory for mutually exclusive data |
Code Examples
Example 1: Beginner – Structure Example
#include <stdio.h> // Include standard input/output library
struct Student // Define a structure
{
int rollNo; // Student roll number
char name[30]; // Student name
float marks; // Student marks
};
int main(void) // Program entry point
{
struct Student student; // Declare a structure variable
student.rollNo = 101; // Assign the roll number
snprintf(student.name, sizeof(student.name), "Alice"); // Copy a string safely into the name array
student.marks = 95.5f; // Assign the marks
printf("Roll No : %d\n", student.rollNo); // Print the roll number
printf("Name : %s\n", student.name); // Print the name
printf("Marks : %.1f\n", student.marks); // Print the marks
return 0; // End the program
}Example 2: Beginner – Union Example
#include <stdio.h> // Include standard input/output library
union Data // Define a union
{
int number; // Integer member
float decimal; // Floating-point member
};
int main(void) // Program entry point
{
union Data value; // Declare a union variable
value.number = 100; // Store an integer
printf("Number = %d\n", value.number); // Print the integer
value.decimal = 25.5f; // Store a float (overwrites previous value)
printf("Decimal = %.1f\n", value.decimal); // Print the float
return 0; // End the program
}Example 3: Intermediate – Array of Structures
#include <stdio.h> // Include standard input/output library
struct Student // Define a structure
{
int rollNo; // Roll number
char name[20]; // Student name
};
int main(void) // Program entry point
{
struct Student students[2] = // Create an array of structures
{
{1, "Alice"}, // Initialize first student
{2, "Bob"} // Initialize second student
};
for (int i = 0; i < 2; i++) // Loop through the array
{
printf("%d %s\n", // Print student details
students[i].rollNo,
students[i].name);
}
return 0; // End the program
}Example 4: Intermediate – Pointer to Structure
#include <stdio.h> // Include standard input/output library
struct Employee // Define a structure
{
int id; // Employee ID
float salary; // Employee salary
};
int main(void) // Program entry point
{
struct Employee employee = {101, 50000.0f}; // Initialize the structure
struct Employee *ptr = &employee; // Create a pointer to the structure
printf("ID = %d\n", ptr->id); // Access member using the arrow operator
printf("Salary = %.2f\n", ptr->salary); // Access member using the arrow operator
return 0; // End the program
}Example 5: Advanced – Nested Structure
#include <stdio.h> // Include standard input/output library
struct Address // Define the Address structure
{
char city[30]; // City name
};
struct Student // Define the Student structure
{
char name[30]; // Student name
struct Address address; // Nested Address structure
};
int main(void) // Program entry point
{
struct Student student = // Initialize the nested structure
{
"Alice",
{"Chennai"}
};
printf("Name : %s\n", student.name); // Print the student's name
printf("City : %s\n", student.address.city); // Print the city
return 0; // End the program
}Common Mistakes and Pitfalls
| Wrong | Correct |
|---|---|
| Using . with a structure pointer | Use -> |
| Assuming a union stores all member values simultaneously | Only one member is valid at a time |
| Forgetting to initialize members | Initialize before use |
| Accessing an inactive union member | Read only the most recently written member (except in implementation-specific scenarios) |
| Ignoring structure padding | Be aware that padding affects structure size |
Wrong:
struct Student student;
struct Student *ptr = &student;
ptr.rollNo = 10;Correct:
struct Student student;
struct Student *ptr = &student;
ptr->rollNo = 10;Best Practices
- Use structures for storing related data that must exist simultaneously.
- Use unions only when members are mutually exclusive.
- Give structures and unions meaningful names.
- Initialize members before accessing them.
- Use pointers for passing large structures to functions to avoid unnecessary copying.
- Consider alignment and padding when working with memory-sensitive applications.
- Use typedef to simplify complex structure declarations when appropriate.
When NOT to Use This
Avoid using structures or unions when:
- A single variable is sufficient.
- Dynamic collections are better represented by linked data structures or dynamic arrays.
- Memory sharing is unnecessary (avoid unions if all values need to exist simultaneously).
- Object-oriented features such as inheritance or polymorphism are required (not available in C).
Summary / Key Takeaways
- Structures and Unions in C programming are user-defined data types.
- Structures allocate separate memory for each member.
- Unions share memory among all members.
- Use the . operator to access structure or union members directly.
- Use the -> operator to access members through a pointer.
- Structures are ideal for storing complete records.
- Unions are useful for saving memory when only one member is needed at a time.
- Arrays, pointers, and nested structures work seamlessly with structures.
- Understanding memory layout helps write efficient and reliable C programs.
FAQ About Structures and Unions in C
1. What is the difference between a structure and a union?
A structure allocates separate memory for each member, allowing all members to hold values simultaneously. A union shares the same memory among all members, so only one member's value is reliably stored at a time.
2. Why are unions memory efficient?
Because all members share the same memory location, a union's size is determined by its largest member (plus any alignment requirements), reducing memory usage when only one value is needed at a time.
3. Can a structure contain another structure?
Yes. This is called a nested structure, and it helps organize related data hierarchically.
4. What is the difference between the . and -> operators?
Use the . operator to access members of a structure or union variable, and use the -> operator to access members through a pointer to a structure or union.
5. When should I use a union instead of a structure?
Use a union when different data types are mutually exclusive, meaning only one of them needs to be stored at any given time—for example, representing different types of sensor readings or protocol messages where only one field is active.