Introduction
Nested structures in C allow you to define structures within other structures, creating hierarchical data organization. This powerful feature enables you to model complex real-world entities that have multiple related components, such as a student with an address, or an employee with contact information and department details.
Key Concepts
Nested Structure: Structure defined inside another structure Member Access: Using dot operator to access nested members Structure Composition: Building complex data types from simpler ones Hierarchical Data: Organizing related information in levels Deep Copy: Copying all levels of nested structures
Basic Nested Structures
1. Simple Nested Structure
#include <stdio.h>
#include <string.h>
// Inner structure for address
struct Address {
char street[50];
char city[30];
char state[20];
int zipCode;
};
// Outer structure containing nested structure
struct Person {
char name[50];
int age;
struct Address address; // Nested structure
float salary;
};
int main() {
struct Person person1;
printf("Nested Structures Demo:\n");
// Initialize person data
strcpy(person1.name, "John Doe");
person1.age = 30;
person1.salary = 50000.0;
// Initialize nested address data
strcpy(person1.address.street, "123 Main St");
strcpy(person1.address.city, "Anytown");
strcpy(person1.address.state, "CA");
person1.address.zipCode = 12345;
// Display person information
printf("Person Details:\n");
printf("Name: %s\n", person1.name);
printf("Age: %d\n", person1.age);
printf("Salary: %.2f\n", person1.salary);
printf("Address:\n");
printf(" Street: %s\n", person1.address.street);
printf(" City: %s\n", person1.address.city);
printf(" State: %s\n", person1.address.state);
printf(" ZIP: %d\n", person1.address.zipCode);
return 0;
}
2. Multiple Nested Structures
#include <stdio.h>
#include <string.h>
// Date structure
struct Date {
int day;
int month;
int year;
};
// Contact information structure
struct Contact {
char phone[15];
char email[50];
};
// Address structure
struct Address {
char street[50];
char city[30];
char state[20];
int zipCode;
};
// Employee structure with multiple nested structures
struct Employee {
int id;
char name[50];
struct Date birthDate; // Nested date
struct Date joinDate; // Another nested date
struct Contact contact; // Nested contact info
struct Address address; // Nested address
float salary;
};
// Function to display employee information
void displayEmployee(struct Employee emp) {
printf("\n=== Employee Information ===\n");
printf("ID: %d\n", emp.id);
printf("Name: %s\n", emp.name);
printf("Birth Date: %02d/%02d/%d\n",
emp.birthDate.day, emp.birthDate.month, emp.birthDate.year);
printf("Join Date: %02d/%02d/%d\n",
emp.joinDate.day, emp.joinDate.month, emp.joinDate.year);
printf("Contact:\n");
printf(" Phone: %s\n", emp.contact.phone);
printf(" Email: %s\n", emp.contact.email);
printf("Address:\n");
printf(" Street: %s\n", emp.address.street);
printf(" City: %s\n", emp.address.city);
printf(" State: %s\n", emp.address.state);
printf(" ZIP: %d\n", emp.address.zipCode);
printf("Salary: $%.2f\n", emp.salary);
}
int main() {
struct Employee emp1;
printf("Multiple Nested Structures:\n");
// Initialize employee data
emp1.id = 1001;
strcpy(emp1.name, "Alice Johnson");
// Initialize birth date
emp1.birthDate.day = 15;
emp1.birthDate.month = 8;
emp1.birthDate.year = 1990;
// Initialize join date
emp1.joinDate.day = 1;
emp1.joinDate.month = 3;
emp1.joinDate.year = 2020;
// Initialize contact information
strcpy(emp1.contact.phone, "+1-555-0123");
strcpy(emp1.contact.email, "alice.johnson@company.com");
// Initialize address
strcpy(emp1.address.street, "456 Oak Avenue");
strcpy(emp1.address.city, "Springfield");
strcpy(emp1.address.state, "IL");
emp1.address.zipCode = 62701;
emp1.salary = 65000.0;
displayEmployee(emp1);
return 0;
}
Complex Nested Structures
1. Student with Courses and Grades
#include <stdio.h>
#include <string.h>
// Grade structure
struct Grade {
char subject[30];
float marks;
char grade;
};
// Academic record structure
struct AcademicRecord {
int semester;
struct Grade grades[5]; // Array of nested structures
int numSubjects;
float gpa;
};
// Personal info structure
struct PersonalInfo {
char firstName[30];
char lastName[30];
int age;
char phone[15];
};
// Student structure with nested structures
struct Student {
int rollNumber;
struct PersonalInfo personal; // Nested personal info
struct AcademicRecord academic; // Nested academic record
char department[30];
};
// Function to calculate GPA
float calculateGPA(struct Student *student) {
float totalPoints = 0;
int subjects = student->academic.numSubjects;
for (int i = 0; i < subjects; i++) {
totalPoints += student->academic.grades[i].marks;
}
student->academic.gpa = totalPoints / subjects;
return student->academic.gpa;
}
// Function to assign letter grades
void assignLetterGrades(struct Student *student) {
for (int i = 0; i < student->academic.numSubjects; i++) {
float marks = student->academic.grades[i].marks;
if (marks >= 90) student->academic.grades[i].grade = 'A';
else if (marks >= 80) student->academic.grades[i].grade = 'B';
else if (marks >= 70) student->academic.grades[i].grade = 'C';
else if (marks >= 60) student->academic.grades[i].grade = 'D';
else student->academic.grades[i].grade = 'F';
}
}
// Function to display student report
void displayStudentReport(struct Student student) {
printf("\n=== Student Report ===\n");
printf("Roll Number: %d\n", student.rollNumber);
printf("Name: %s %s\n", student.personal.firstName, student.personal.lastName);
printf("Age: %d\n", student.personal.age);
printf("Phone: %s\n", student.personal.phone);
printf("Department: %s\n", student.department);
printf("Semester: %d\n", student.academic.semester);
printf("\nGrades:\n");
printf("%-20s %-10s %-10s\n", "Subject", "Marks", "Grade");
printf("----------------------------------------\n");
for (int i = 0; i < student.academic.numSubjects; i++) {
printf("%-20s %-10.2f %-10c\n",
student.academic.grades[i].subject,
student.academic.grades[i].marks,
student.academic.grades[i].grade);
}
printf("----------------------------------------\n");
printf("GPA: %.2f\n", student.academic.gpa);
}
int main() {
struct Student student1;
printf("Complex Nested Structures - Student Management:\n");
// Initialize student data
student1.rollNumber = 2021001;
strcpy(student1.personal.firstName, "Emma");
strcpy(student1.personal.lastName, "Wilson");
student1.personal.age = 20;
strcpy(student1.personal.phone, "+1-555-0199");
strcpy(student1.department, "Computer Science");
// Initialize academic record
student1.academic.semester = 3;
student1.academic.numSubjects = 4;
// Initialize grades
strcpy(student1.academic.grades[0].subject, "Data Structures");
student1.academic.grades[0].marks = 88.5;
strcpy(student1.academic.grades[1].subject, "Algorithms");
student1.academic.grades[1].marks = 92.0;
strcpy(student1.academic.grades[2].subject, "Database Systems");
student1.academic.grades[2].marks = 85.5;
strcpy(student1.academic.grades[3].subject, "Web Development");
student1.academic.grades[3].marks = 90.0;
// Calculate GPA and assign letter grades
calculateGPA(&student1);
assignLetterGrades(&student1);
displayStudentReport(student1);
return 0;
}
2. Company with Departments and Employees
#include <stdio.h>
#include <string.h>
// Employee structure
struct Employee {
int empId;
char name[50];
char position[30];
float salary;
};
// Department structure with array of employees
struct Department {
int deptId;
char deptName[30];
char manager[50];
struct Employee employees[10]; // Array of nested structures
int empCount;
float totalBudget;
};
// Company structure with multiple departments
struct Company {
char companyName[50];
char address[100];
struct Department departments[5]; // Array of nested structures
int deptCount;
int totalEmployees;
};
// Function to add employee to department
void addEmployee(struct Department *dept, int id, char name[], char position[], float salary) {
if (dept->empCount < 10) {
dept->employees[dept->empCount].empId = id;
strcpy(dept->employees[dept->empCount].name, name);
strcpy(dept->employees[dept->empCount].position, position);
dept->employees[dept->empCount].salary = salary;
dept->empCount++;
}
}
// Function to calculate department salary total
float calculateDepartmentSalary(struct Department dept) {
float total = 0;
for (int i = 0; i < dept.empCount; i++) {
total += dept.employees[i].salary;
}
return total;
}
// Function to display company structure
void displayCompanyStructure(struct Company company) {
printf("\n=== Company Structure ===\n");
printf("Company: %s\n", company.companyName);
printf("Address: %s\n", company.address);
printf("Total Departments: %d\n", company.deptCount);
printf("Total Employees: %d\n", company.totalEmployees);
for (int i = 0; i < company.deptCount; i++) {
struct Department dept = company.departments[i];
printf("\n--- Department: %s ---\n", dept.deptName);
printf("Manager: %s\n", dept.manager);
printf("Budget: $%.2f\n", dept.totalBudget);
printf("Employees (%d):\n", dept.empCount);
for (int j = 0; j < dept.empCount; j++) {
struct Employee emp = dept.employees[j];
printf(" %d. %s - %s ($%.2f)\n",
emp.empId, emp.name, emp.position, emp.salary);
}
float deptSalaryTotal = calculateDepartmentSalary(dept);
printf("Total Salary Cost: $%.2f\n", deptSalaryTotal);
}
}
int main() {
struct Company techCorp;
printf("Company Management with Nested Structures:\n");
// Initialize company
strcpy(techCorp.companyName, "TechCorp Solutions");
strcpy(techCorp.address, "123 Tech Street, Silicon Valley, CA");
techCorp.deptCount = 2;
techCorp.totalEmployees = 0;
// Initialize IT Department
techCorp.departments[0].deptId = 1;
strcpy(techCorp.departments[0].deptName, "Information Technology");
strcpy(techCorp.departments[0].manager, "Sarah Chen");
techCorp.departments[0].empCount = 0;
techCorp.departments[0].totalBudget = 500000.0;
// Add employees to IT department
addEmployee(&techCorp.departments[0], 101, "Mike Johnson", "Software Engineer", 75000);
addEmployee(&techCorp.departments[0], 102, "Lisa Wang", "Senior Developer", 85000);
addEmployee(&techCorp.departments[0], 103, "David Brown", "System Admin", 65000);
// Initialize Marketing Department
techCorp.departments[1].deptId = 2;
strcpy(techCorp.departments[1].deptName, "Marketing");
strcpy(techCorp.departments[1].manager, "Jennifer Adams");
techCorp.departments[1].empCount = 0;
techCorp.departments[1].totalBudget = 300000.0;
// Add employees to Marketing department
addEmployee(&techCorp.departments[1], 201, "Alex Rodriguez", "Marketing Manager", 70000);
addEmployee(&techCorp.departments[1], 202, "Emily Davis", "Content Creator", 55000);
// Calculate total employees
techCorp.totalEmployees = techCorp.departments[0].empCount + techCorp.departments[1].empCount;
displayCompanyStructure(techCorp);
return 0;
}
Arrays of Nested Structures
Student Database System
#include <stdio.h>
#include <string.h>
// Address structure
struct Address {
char street[50];
char city[30];
int pincode;
};
// Course structure
struct Course {
char courseName[30];
int credits;
float grade;
};
// Student structure with nested components
struct Student {
int rollNo;
char name[50];
struct Address homeAddress; // Nested address
struct Course courses[6]; // Array of nested courses
int courseCount;
float cgpa;
};
// Function to add course to student
void addCourse(struct Student *student, char courseName[], int credits, float grade) {
if (student->courseCount < 6) {
strcpy(student->courses[student->courseCount].courseName, courseName);
student->courses[student->courseCount].credits = credits;
student->courses[student->courseCount].grade = grade;
student->courseCount++;
}
}
// Function to calculate CGPA
void calculateCGPA(struct Student *student) {
float totalPoints = 0;
int totalCredits = 0;
for (int i = 0; i < student->courseCount; i++) {
totalPoints += student->courses[i].grade * student->courses[i].credits;
totalCredits += student->courses[i].credits;
}
student->cgpa = (totalCredits > 0) ? totalPoints / totalCredits : 0;
}
// Function to display student database
void displayStudentDatabase(struct Student students[], int count) {
printf("\n=== Student Database ===\n");
for (int i = 0; i < count; i++) {
printf("\nStudent %d:\n", i + 1);
printf("Roll No: %d\n", students[i].rollNo);
printf("Name: %s\n", students[i].name);
printf("Address: %s, %s - %d\n",
students[i].homeAddress.street,
students[i].homeAddress.city,
students[i].homeAddress.pincode);
printf("Courses:\n");
for (int j = 0; j < students[i].courseCount; j++) {
printf(" %s (Credits: %d, Grade: %.1f)\n",
students[i].courses[j].courseName,
students[i].courses[j].credits,
students[i].courses[j].grade);
}
printf("CGPA: %.2f\n", students[i].cgpa);
printf("------------------------\n");
}
}
int main() {
struct Student database[3];
printf("Student Database with Nested Structures:\n");
// Initialize Student 1
database[0].rollNo = 1001;
strcpy(database[0].name, "Raj Patel");
strcpy(database[0].homeAddress.street, "15 MG Road");
strcpy(database[0].homeAddress.city, "Mumbai");
database[0].homeAddress.pincode = 400001;
database[0].courseCount = 0;
addCourse(&database[0], "Mathematics", 4, 8.5);
addCourse(&database[0], "Physics", 3, 9.0);
addCourse(&database[0], "Chemistry", 3, 7.5);
calculateCGPA(&database[0]);
// Initialize Student 2
database[1].rollNo = 1002;
strcpy(database[1].name, "Priya Sharma");
strcpy(database[1].homeAddress.street, "22 Park Street");
strcpy(database[1].homeAddress.city, "Delhi");
database[1].homeAddress.pincode = 110001;
database[1].courseCount = 0;
addCourse(&database[1], "Computer Science", 4, 9.5);
addCourse(&database[1], "Mathematics", 4, 8.0);
addCourse(&database[1], "English", 2, 8.5);
calculateCGPA(&database[1]);
// Initialize Student 3
database[2].rollNo = 1003;
strcpy(database[2].name, "Arjun Kumar");
strcpy(database[2].homeAddress.street, "8 Brigade Road");
strcpy(database[2].homeAddress.city, "Bangalore");
database[2].homeAddress.pincode = 560001;
database[2].courseCount = 0;
addCourse(&database[2], "Electronics", 4, 8.8);
addCourse(&database[2], "Mathematics", 4, 7.8);
addCourse(&database[2], "Physics", 3, 8.2);
calculateCGPA(&database[2]);
displayStudentDatabase(database, 3);
return 0;
}
Pointer to Nested Structures
Dynamic Allocation Example
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// Point structure
struct Point {
float x, y;
};
// Rectangle structure with nested points
struct Rectangle {
struct Point topLeft;
struct Point bottomRight;
float area;
float perimeter;
};
// Function to calculate rectangle properties
void calculateProperties(struct Rectangle *rect) {
float width = rect->bottomRight.x - rect->topLeft.x;
float height = rect->topLeft.y - rect->bottomRight.y;
rect->area = width * height;
rect->perimeter = 2 * (width + height);
}
// Function to display rectangle information
void displayRectangle(struct Rectangle *rect) {
printf("Rectangle Properties:\n");
printf("Top-Left: (%.2f, %.2f)\n", rect->topLeft.x, rect->topLeft.y);
printf("Bottom-Right: (%.2f, %.2f)\n", rect->bottomRight.x, rect->bottomRight.y);
printf("Area: %.2f\n", rect->area);
printf("Perimeter: %.2f\n", rect->perimeter);
}
// Function to create rectangle dynamically
struct Rectangle* createRectangle(float x1, float y1, float x2, float y2) {
struct Rectangle *rect = malloc(sizeof(struct Rectangle));
if (rect != NULL) {
rect->topLeft.x = x1;
rect->topLeft.y = y1;
rect->bottomRight.x = x2;
rect->bottomRight.y = y2;
calculateProperties(rect);
}
return rect;
}
int main() {
printf("Pointer to Nested Structures:\n");
// Create rectangle dynamically
struct Rectangle *rect1 = createRectangle(0.0, 10.0, 8.0, 2.0);
if (rect1 != NULL) {
displayRectangle(rect1);
free(rect1);
}
// Static allocation example
struct Rectangle rect2;
rect2.topLeft.x = 5.0;
rect2.topLeft.y = 15.0;
rect2.bottomRight.x = 12.0;
rect2.bottomRight.y = 8.0;
calculateProperties(&rect2);
printf("\nStatic Rectangle:\n");
displayRectangle(&rect2);
return 0;
}
Important Points
- Access nested members using multiple dot operators
- Initialize all levels of nested structures properly
- Memory layout follows structure order and alignment
- Passing nested structures can be done by value or reference
- Arrays of nested structures create complex data organizations
- Pointer access uses arrow operator for each level
- Function parameters can accept nested structure pointers
- Memory management important for dynamic nested structures
Best Practices
- Use meaningful names for nested structure members
- Initialize all members to avoid garbage values
- Create helper functions for common operations
- Group related data logically in nested structures
- Validate nested data before processing
- Use typedef to simplify complex nested declarations
- Document structure hierarchy clearly
- Consider memory efficiency when designing nested structures
Summary
Nested structures in C enable hierarchical data organization by embedding structures within other structures. This allows modeling complex real-world entities with multiple related components. Access requires multiple dot operators or arrow operators for pointers. Nested structures can be combined with arrays and pointers for sophisticated data management systems. Proper initialization and memory management are crucial for nested structure applications.
Part of BCA Programming with C Course (UGCOA22J201)