Structures in C
Structures allow you to group variables of different data types under a single name, creating user-defined data types.
"A structure is a user-defined data type that allows you to combine data items of different kinds."
What is a Structure?
A structure is a user-defined data type that allows grouping of variables of different data types under a single name. Structures are used to represent records or collections of related data.
Defining a Structure
Basic Structure Definition
// Structure definition
struct structure_name {
data_type member1;
data_type member2;
// ... more members
};
// Example: Student structure
struct Student {
int roll_number;
char name[50];
float marks;
char grade;
};
Structure Variable Declaration
// Method 1: Declare after definition
struct Student student1, student2;
// Method 2: Declare with definition
struct Employee {
int id;
char name[50];
float salary;
} emp1, emp2;
// Method 3: Using typedef (creates alias)
typedef struct {
int day;
int month;
int year;
} Date;
Date today, birthday;
Accessing Structure Members
Structure members are accessed using the dot (.) operator.
Basic Member Access
#include <stdio.h>
#include <string.h>
struct Student {
int roll_number;
char name[50];
float marks;
};
int main() {
struct Student s1;
// Assign values to members
s1.roll_number = 101;
strcpy(s1.name, "John Doe");
s1.marks = 85.5;
// Access and display members
printf("Roll Number: %d\n", s1.roll_number);
printf("Name: %s\n", s1.name);
printf("Marks: %.2f\n", s1.marks);
return 0;
}
Structure Initialization
#include <stdio.h>
#include <string.h>
struct Student {
int roll_number;
char name[50];
float marks;
};
int main() {
// Method 1: Initialize during declaration
struct Student s1 = {101, "Alice", 92.5};
// Method 2: Designated initialization (C99)
struct Student s2 = {
.roll_number = 102,
.name = "Bob",
.marks = 88.0
};
// Method 3: Partial initialization (remaining members set to 0)
struct Student s3 = {103, "Charlie"};
printf("Student 1: %d, %s, %.2f\n", s1.roll_number, s1.name, s1.marks);
printf("Student 2: %d, %s, %.2f\n", s2.roll_number, s2.name, s2.marks);
printf("Student 3: %d, %s, %.2f\n", s3.roll_number, s3.name, s3.marks);
return 0;
}
Array of Structures
#include <stdio.h>
#include <string.h>
struct Student {
int roll_number;
char name[50];
float marks;
};
int main() {
struct Student students[3];
// Initialize array of structures
for (int i = 0; i < 3; i++) {
printf("Enter details for student %d:\n", i + 1);
printf("Roll Number: ");
scanf("%d", &students[i].roll_number);
printf("Name: ");
scanf("%s", students[i].name);
printf("Marks: ");
scanf("%f", &students[i].marks);
}
// Display all students
printf("\nStudent Details:\n");
for (int i = 0; i < 3; i++) {
printf("Student %d: %d, %s, %.2f\n",
i + 1, students[i].roll_number,
students[i].name, students[i].marks);
}
return 0;
}
Structure Pointers
You can create pointers to structures and access members using the arrow (->) operator.
Structure Pointers
#include <stdio.h>
#include <string.h>
struct Student {
int roll_number;
char name[50];
float marks;
};
int main() {
struct Student s1 = {101, "Alice", 92.5};
struct Student *ptr = &s1;
// Access members using pointer
printf("Roll Number: %d\n", ptr->roll_number);
printf("Name: %s\n", ptr->name);
printf("Marks: %.2f\n", ptr->marks);
// Modify members using pointer
ptr->marks = 95.0;
printf("Updated Marks: %.2f\n", ptr->marks);
return 0;
}
Dynamic Memory Allocation for Structures
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Student {
int roll_number;
char name[50];
float marks;
};
int main() {
struct Student *ptr;
// Allocate memory for structure
ptr = (struct Student*)malloc(sizeof(struct Student));
if (ptr == NULL) {
printf("Memory allocation failed\n");
return 1;
}
// Assign values
ptr->roll_number = 101;
strcpy(ptr->name, "Dynamic Student");
ptr->marks = 87.5;
// Display values
printf("Roll Number: %d\n", ptr->roll_number);
printf("Name: %s\n", ptr->name);
printf("Marks: %.2f\n", ptr->marks);
// Free allocated memory
free(ptr);
return 0;
}
Nested Structures
Structures can contain other structures as members.
Basic Nested Structures
#include <stdio.h>
#include <string.h>
struct Address {
char street[50];
char city[30];
char state[30];
int pincode;
};
struct Employee {
int id;
char name[50];
struct Address addr;
float salary;
};
int main() {
struct Employee emp;
// Assign values
emp.id = 1001;
strcpy(emp.name, "John Smith");
strcpy(emp.addr.street, "123 Main St");
strcpy(emp.addr.city, "New York");
strcpy(emp.addr.state, "NY");
emp.addr.pincode = 10001;
emp.salary = 50000.0;
// Display values
printf("Employee ID: %d\n", emp.id);
printf("Name: %s\n", emp.name);
printf("Address: %s, %s, %s - %d\n",
emp.addr.street, emp.addr.city,
emp.addr.state, emp.addr.pincode);
printf("Salary: %.2f\n", emp.salary);
return 0;
}
Structure within Structure Pointer
#include <stdio.h>
#include <string.h>
struct Date {
int day, month, year;
};
struct Person {
char name[50];
struct Date birth_date;
};
int main() {
struct Person person;
struct Person *ptr = &person;
// Assign values using pointer
strcpy(ptr->name, "Alice Johnson");
ptr->birth_date.day = 15;
ptr->birth_date.month = 8;
ptr->birth_date.year = 1995;
// Display values
printf("Name: %s\n", ptr->name);
printf("Birth Date: %d/%d/%d\n",
ptr->birth_date.day,
ptr->birth_date.month,
ptr->birth_date.year);
return 0;
}
Structure Padding and Packing
Structures may have padding bytes for memory alignment.
Structure Size and Padding
#include <stdio.h>
struct Example {
char c; // 1 byte
int i; // 4 bytes
char c2; // 1 byte
};
int main() {
struct Example ex;
printf("Size of char: %lu bytes\n", sizeof(char));
printf("Size of int: %lu bytes\n", sizeof(int));
printf("Size of structure: %lu bytes\n", sizeof(struct Example));
// Structure may have padding for alignment
printf("Address of c: %p\n", &ex.c);
printf("Address of i: %p\n", &ex.i);
printf("Address of c2: %p\n", &ex.c2);
return 0;
}
typedef with Structures
typedef creates aliases for structure types, making code cleaner.
Using typedef with Structures
#include <stdio.h>
#include <string.h>
// Method 1: typedef with struct
typedef struct {
int x, y;
} Point;
// Method 2: typedef with named struct
typedef struct Rectangle {
Point top_left;
int width, height;
} Rectangle;
int main() {
Point p1 = {10, 20};
Rectangle rect = {{0, 0}, 100, 50};
printf("Point: (%d, %d)\n", p1.x, p1.y);
printf("Rectangle: Top-left(%d, %d), Width: %d, Height: %d\n",
rect.top_left.x, rect.top_left.y,
rect.width, rect.height);
return 0;
}
Passing Structures to Functions
Pass by Value
#include <stdio.h>
#include <string.h>
struct Student {
int roll_number;
char name[50];
float marks;
};
// Pass by value (creates copy)
void displayStudent(struct Student s) {
printf("Roll: %d, Name: %s, Marks: %.2f\n",
s.roll_number, s.name, s.marks);
}
int main() {
struct Student s1 = {101, "Alice", 92.5};
displayStudent(s1);
return 0;
}
Pass by Reference
#include <stdio.h>
#include <string.h>
struct Student {
int roll_number;
char name[50];
float marks;
};
// Pass by reference (modifies original)
void updateMarks(struct Student *s, float new_marks) {
s->marks = new_marks;
}
int main() {
struct Student s1 = {101, "Alice", 92.5};
printf("Before update: %.2f\n", s1.marks);
updateMarks(&s1, 95.0);
printf("After update: %.2f\n", s1.marks);
return 0;
}
Bit Fields in Structures
Bit fields allow packing of data in structures at the bit level.
Bit Field Example
#include <stdio.h>
struct Flags {
unsigned int flag1 : 1; // 1 bit
unsigned int flag2 : 1; // 1 bit
unsigned int flag3 : 1; // 1 bit
unsigned int data : 5; // 5 bits
};
int main() {
struct Flags f;
f.flag1 = 1;
f.flag2 = 0;
f.flag3 = 1;
f.data = 15; // 5-bit value (0-31)
printf("Size of structure: %lu bytes\n", sizeof(struct Flags));
printf("Flags: %d, %d, %d, Data: %d\n",
f.flag1, f.flag2, f.flag3, f.data);
return 0;
}
Practical Examples
1. Student Management System
#include <stdio.h>
#include <string.h>
#define MAX_STUDENTS 100
struct Student {
int roll_number;
char name[50];
float marks[5]; // marks in 5 subjects
float average;
char grade;
};
void calculateGrade(struct Student *s) {
s->average = 0;
for (int i = 0; i < 5; i++) {
s->average += s->marks[i];
}
s->average /= 5;
if (s->average >= 90) s->grade = 'A';
else if (s->average >= 80) s->grade = 'B';
else if (s->average >= 70) s->grade = 'C';
else if (s->average >= 60) s->grade = 'D';
else s->grade = 'F';
}
int main() {
struct Student students[MAX_STUDENTS];
int n;
printf("Enter number of students: ");
scanf("%d", &n);
for (int i = 0; i < n; i++) {
printf("\nEnter details for student %d:\n", i + 1);
printf("Roll Number: ");
scanf("%d", &students[i].roll_number);
printf("Name: ");
scanf("%s", students[i].name);
printf("Enter marks in 5 subjects: ");
for (int j = 0; j < 5; j++) {
scanf("%f", &students[i].marks[j]);
}
calculateGrade(&students[i]);
}
// Display results
printf("\nStudent Report:\n");
printf("Roll\tName\t\tAverage\tGrade\n");
for (int i = 0; i < n; i++) {
printf("%d\t%s\t\t%.2f\t%c\n",
students[i].roll_number,
students[i].name,
students[i].average,
students[i].grade);
}
return 0;
}
Advantages of Structures
- Group related data together
- Create user-defined data types
- Improve code organization and readability
- Enable complex data representations
- Support for nested structures
Limitations of Structures
- Structure padding can waste memory
- No built-in methods or functions
- Data hiding is not supported
- Operator overloading is not possible
Best Practices
- Use meaningful structure names and member names
- Consider memory alignment and padding
- Use typedef for cleaner code
- Pass structures by reference to functions when modifying
- Initialize structure members properly
- Document the purpose and usage of structures
Conclusion
Structures are fundamental to organizing complex data in C programs. They allow you to create custom data types that group related information together. Mastering structures is essential for building real-world applications. Practice creating and using different types of structures to become proficient! 🚀