In C programming, a structure is a user-defined data type that allows you to group together variables of different data types under a single name. Structures provide a way to create more complex data types that can represent real-world entities more effectively. In this section, we'll delve into the basics of structures and how they are defined.
A structure in C is defined using the struct
keyword followed by a name that you choose for the structure. Inside the curly braces { }
, you specify the members of the structure, which can be of any data type, including primitive types like int, float, char, or other structures.
struct Student {
int roll_number;
char name[50];
float marks;
};
In this example, we’ve defined a structure called Student
with three members: roll_number
of type int, name
of type character array (string), and marks
of type float.
#include
// Define a structure
struct student {
int roll_number;
char name[50];
float marks;
};
int main() {
// Declare a structure variable
struct student s1;
// Accessing and assigning values to structure members
s1.roll_number = 1;
strcpy(s1.name, "John");
s1.marks = 95.5;
// Printing structure members
printf("Roll Number: %d\n", s1.roll_number);
printf("Name: %s\n", s1.name);
printf("Marks: %.2f\n", s1.marks);
return 0;
}
// output //
Roll Number: 1
Name: John
Marks: 95.50
student
, which has three members: roll_number
, name
, and marks
.s1
of type struct student
.s1
using the dot (.
) operator.You can access the members of a structure using the dot .
operator followed by the member name. This allows you to read or modify the values stored in the structure members.
struct Student s1;
s1.roll_number = 101;
strcpy(s1.name, "John");
s1.marks = 85.5;
In this code snippet, we’ve declared a structure variable s1
of type Student
and assigned values to its members using the dot operator.
Structures can also be nested within other structures, allowing you to create more complex data structures. Here’s an example
#include
struct date {
int day;
int month;
int year;
};
struct employee {
char name[50];
struct date dob;
};
int main() {
struct employee emp1 = {"Alice", {25, 3, 1990}};
printf("Employee Name: %s\n", emp1.name);
printf("Date of Birth: %d-%d-%d\n", emp1.dob.day, emp1.dob.month, emp1.dob.year);
return 0;
}
date
, which represents a date with members day
, month
, and year
.employee
, which contains a member dob
of type struct date
.main
function, we declare a variable emp1
of type struct employee
and initialize its members..
) operator.
// output //
Employee Name: Alice
Date of Birth: 25-3-1990
You can create arrays of structures to store multiple records of the same type. This is useful for managing collections of data. Here’s an example
#include
struct employee {
char name[50];
int emp_id;
float salary;
};
int main() {
struct employee employees[3] = {
{"John", 101, 50000.0},
{"Alice", 102, 60000.0},
{"Bob", 103, 55000.0}
};
for (int i = 0; i < 3; i++) {
printf("Employee %d\n", i+1);
printf("Name: %s\n", employees[i].name);
printf("Employee ID: %d\n", employees[i].emp_id);
printf("Salary: %.2f\n", employees[i].salary);
printf("\n");
}
return 0;
}
employee
to represent employee data with members name
, emp_id
, and salary
.employees
of size 3, where each element is of type struct employee
.{}
syntax.
// output //
Employee 1
Name: John
Employee ID: 101
Salary: 50000.00
Employee 2
Name: Alice
Employee ID: 102
Salary: 60000.00
Employee 3
Name: Bob
Employee ID: 103
Salary: 55000.00
Passing structures to functions allows you to manipulate structure data within functions. Here’s an example demonstrating how to pass a structure to a function
#include
// Define a structure
struct student {
int roll_number;
char name[50];
float marks;
};
// Function to display student details
void displayStudent(struct student s) {
printf("Roll Number: %d\n", s.roll_number);
printf("Name: %s\n", s.name);
printf("Marks: %.2f\n", s.marks);
}
int main() {
// Declare a structure variable
struct student s1 = {1, "John", 95.5};
// Pass structure to the function
displayStudent(s1);
return 0;
}
student
with three members: roll_number
, name
, and marks
.displayStudent
that takes a structure of type student
as a parameter and displays its details.main
function, we create a structure variable s1
and initialize it with some values.s1
to the displayStudent
function, where its details are printed.
// output //
Roll Number: 1
Name: John
Marks: 95.50
In C programming, unions provide a way to define a data type that can hold different types of data members, but only one at a time. Unlike structures where all members are stored separately in memory, union members share the same memory location. This means that modifying one member can affect the values of other members.
The syntax for defining a union in C is similar to that of a structure. It starts with the union
keyword followed by the union name and a list of member variables enclosed in curly braces {}.
union union_name {
data_type member1;
data_type member2;
// More members...
};
Unlike structures, unions allocate memory only for the largest member. This is because all members share the same memory location.
Union members are accessed using the dot (.
) operator, similar to structures.
Let’s dive into some examples to understand unions better.
#include
union SampleUnion {
int num;
float fnum;
};
int main() {
union SampleUnion u;
u.num = 10;
printf("Integer: %d\n", u.num);
u.fnum = 3.14;
printf("Float: %.2f\n", u.fnum);
return 0;
}
// output //
Integer: 10
Float: 3.14
In this example, we define a union SampleUnion
with two members: an integer num
and a float fnum
. We then assign values to both members and print them. Notice how modifying one member affects the other member because they share the same memory location.
In this example, we have a union Employee
containing an employee ID and salary. We then have a structure Department
which includes the department name and the Employee
union. We demonstrate how to access and modify union members within a structure.
#include
union Employee {
int emp_id;
float salary;
};
struct Department {
char name[20];
union Employee emp_info;
};
int main() {
struct Department dept;
strcpy(dept.name, "Finance");
dept.emp_info.emp_id = 1001;
printf("Employee ID: %d\n", dept.emp_info.emp_id);
dept.emp_info.salary = 50000.0;
printf("Salary: %.2f\n", dept.emp_info.salary);
return 0;
}
// output //
Employee ID: 1001
Salary: 50000.00
Unions can be nested within other unions, structures, or even themselves. This allows for more complex data structures where different levels of data abstraction are required.
#include
union OuterUnion {
int x;
union InnerUnion {
char c;
float f;
} inner;
};
int main() {
union OuterUnion ou;
ou.x = 10;
printf("Outer Union Integer: %d\n", ou.x);
ou.inner.f = 3.14;
printf("Inner Union Float: %.2f\n", ou.inner.f);
return 0;
}
// output //
Outer Union Integer: 10
Inner Union Float: 3.14
In this example, InnerUnion
is nested within OuterUnion
, demonstrating how unions can be organized hierarchically.
Unions can also be used with bit fields to create compact data structures where individual bits represent specific flags or attributes.
#include
union Status {
struct {
unsigned int ready : 1;
unsigned int error : 1;
unsigned int busy : 1;
} bits;
unsigned int value;
};
int main() {
union Status s;
s.value = 5; // binary: 101
printf("Ready: %d\n", s.bits.ready);
printf("Error: %d\n", s.bits.error);
printf("Busy: %d\n", s.bits.busy);
return 0;
}
// output //
Ready: 1
Error: 0
Busy: 1
In this example, the Status
union uses a bit field structure to represent individual status flags within a single integer.
Type punning exploits the fact that unions share the same memory space for all their members. When you access one member of a union, you can effectively interpret the memory contents as if it were any other member of the union. This allows for flexible data manipulation and can be particularly useful in certain scenarios.
#include
union TypePunning {
int i;
float f;
};
int main() {
union TypePunning tp;
tp.f = 3.14;
printf("Float Value: %.2f\n", tp.f);
printf("Integer Value: %d\n", tp.i);
return 0;
}
// output //
Float Value: 3.14
Integer Value: 1078523331
In this example, we define a union TypePunning
with two members: an integer i
and a float f
. We then assign the value 3.14
to the float member f
. However, when we print the integer member i
, we get 1078523331
instead of what we might expect.
The output 1078523331
is the binary representation of the floating-point value 3.14
interpreted as an integer. This happens because we accessed the integer member i
after storing a value in the float member f
. Since both members share the same memory location, accessing one member after modifying another can lead to type punning.
In this chapter, we covered the basics and advance concepts of structures and unions in C language. Structures allow you to group variables of different data types together, while unions enable you to use the same memory location for different types of data. Understanding structures and unions is essential for building complex data structures and managing memory efficiently in C programming. Practice and experimentation with these concepts will deepen your understanding and proficiency in C programming. Happy coding! ❤️