Structures and Unions in C
Arrays allow storing multiple values of the same type. But real-world data often has multiple properties of different types. For example, a student has a name (string), age (int), and GPA (float). C provides structures and unions to group different types of data under one name.
Structures in C
A structure is a user-defined data type that groups together variables of different data types under a single name. Each variable inside the structure is called a member or field. All members exist in memory simultaneously.
Syntax — Defining a Structure
struct structure_name
{
data_type member1;
data_type member2;
data_type member3;
...
};
Example — Student Structure
struct Student
{
char name[50];
int age;
float gpa;
};
Declaring Structure Variables
struct Student s1; // declares a variable s1 of type struct Student
struct Student s2, s3; // multiple variables
Accessing Structure Members — Dot Operator
Members of a structure are accessed using the dot operator (.).
#include <stdio.h>
#include <string.h>
struct Student
{
char name[50];
int age;
float gpa;
};
int main()
{
struct Student s1;
strcpy(s1.name, "Alice");
s1.age = 20;
s1.gpa = 8.75;
printf("Name : %s\n", s1.name);
printf("Age : %d\n", s1.age);
printf("GPA : %.2f\n", s1.gpa);
return 0;
}
Output
Name : Alice
Age : 20
GPA : 8.75
Initializing a Structure at Declaration
struct Student s1 = {"Bob", 21, 9.1};
Array of Structures
An array of structures is used to store information about multiple entities of the same type.
#include <stdio.h>
#include <string.h>
struct Student
{
char name[50];
int age;
float gpa;
};
int main()
{
struct Student students[3];
strcpy(students[0].name, "Alice"); students[0].age = 20; students[0].gpa = 8.75;
strcpy(students[1].name, "Bob"); students[1].age = 21; students[1].gpa = 7.90;
strcpy(students[2].name, "Carol"); students[2].age = 22; students[2].gpa = 9.20;
printf("%-15s %-5s %s\n", "Name", "Age", "GPA");
for (int i = 0; i < 3; i++)
{
printf("%-15s %-5d %.2f\n",
students[i].name,
students[i].age,
students[i].gpa);
}
return 0;
}
Output
Name Age GPA
Alice 20 8.75
Bob 21 7.90
Carol 22 9.20
Nested Structures
A structure can have another structure as a member.
#include <stdio.h>
struct Date
{
int day;
int month;
int year;
};
struct Employee
{
char name[50];
int id;
struct Date joinDate; // nested structure
};
int main()
{
struct Employee emp;
emp.id = 101;
emp.joinDate.day = 15;
emp.joinDate.month = 8;
emp.joinDate.year = 2020;
printf("Employee ID : %d\n", emp.id);
printf("Joined on : %d/%d/%d\n",
emp.joinDate.day,
emp.joinDate.month,
emp.joinDate.year);
return 0;
}
Output
Employee ID : 101
Joined on : 15/8/2020
Pointers to Structures — Arrow Operator
When using a pointer to access structure members, the arrow operator (->) is used instead of the dot operator.
#include <stdio.h>
struct Point
{
int x;
int y;
};
int main()
{
struct Point p = {3, 7};
struct Point *ptr = &p;
printf("x = %d\n", ptr->x); // using arrow operator
printf("y = %d\n", ptr->y);
ptr->x = 10; // modifying via pointer
printf("Updated x = %d\n", ptr->x);
return 0;
}
Output
x = 3
y = 7
Updated x = 10
Passing Structure to a Function
#include <stdio.h>
struct Rectangle
{
float length;
float width;
};
float area(struct Rectangle r)
{
return r.length * r.width;
}
int main()
{
struct Rectangle rect = {6.0, 4.5};
printf("Area = %.2f\n", area(rect)); // Area = 27.00
return 0;
}
typedef with Structures
typedef creates an alias for a data type, allowing the structure to be used without writing struct every time.
typedef struct
{
char name[50];
int age;
} Person;
// Now use Person instead of struct Person
Person p1;
#include <stdio.h>
typedef struct
{
char name[50];
int age;
} Person;
int main()
{
Person p1 = {"David", 30};
printf("Name: %s, Age: %d\n", p1.name, p1.age);
return 0;
}
Unions in C
A union is similar to a structure, but with one critical difference: all members of a union share the same memory space. Only one member can hold a value at any given time. The size of a union is equal to the size of its largest member.
Syntax
union union_name
{
data_type member1;
data_type member2;
...
};
Example — Union
#include <stdio.h>
union Data
{
int intVal;
float floatVal;
char charVal;
};
int main()
{
union Data d;
d.intVal = 100;
printf("intVal = %d\n", d.intVal);
d.floatVal = 3.14;
printf("floatVal = %.2f\n", d.floatVal);
printf("intVal = %d\n", d.intVal); // corrupted! floatVal overwrote it
d.charVal = 'Z';
printf("charVal = %c\n", d.charVal);
return 0;
}
Output
intVal = 100
floatVal = 3.14
intVal = 1078523331 ← corrupted because floatVal overwrote the memory
charVal = Z
Key Point: Only use the most recently assigned member of a union. Accessing others gives garbage values.
Structure vs Union — Key Differences
| Feature | Structure | Union |
|---|---|---|
| Memory | Each member has its own memory | All members share the same memory |
| Size | Sum of all member sizes (+ padding) | Size of the largest member |
| Access | All members can be used at same time | Only one member can be used at a time |
| Use Case | When all fields are needed simultaneously | When only one field is needed at a time |
Memory Size Example
struct Example { int a; float b; char c; };
// Size = 4 + 4 + 1 = 9 bytes (possibly 12 with padding)
union Example { int a; float b; char c; };
// Size = 4 bytes (size of largest member: int or float)
When to Use Unions
Unions are useful when:
- Memory is very limited (e.g., embedded systems).
- A variable might hold one of several types at any given time (like a generic data container).
- Parsing binary data formats where the same bytes represent different things in different contexts.
Summary
Structures group multiple variables of different types together, with each member having its own dedicated memory. They are ideal for representing real-world entities like students, employees, and products. Unions also group different types but share memory — only one member is valid at any time, making them memory-efficient. The dot operator . accesses members of a structure variable, while the arrow operator -> is used with structure pointers. Together, structures and unions are the foundation of C's approach to user-defined data types.
