Structures and Unions

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.

Definition of a Structure

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.

Code Snippet

				
					#include <stdio.h>

// 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

				
			

Explanation:

  • In this example, we define a structure named student, which has three members: roll_number, name, and marks.
  • We declare a variable s1 of type struct student.
  • We assign values to the members of s1 using the dot (.) operator.
  • Finally, we print the values of the structure members.

Accessing Structure Members

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.

Nested Structures

Structures can also be nested within other structures, allowing you to create more complex data structures. Here’s an example

				
					#include <stdio.h>

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;
}

				
			

Explanation:

  • In this example, we define a structure named date, which represents a date with members day, month, and year.
  • We then define another structure named employee, which contains a member dob of type struct date.
  • In the main function, we declare a variable emp1 of type struct employee and initialize its members.
  • We access the nested structure members using the dot (.) operator.
				
					// output //
Employee Name: Alice
Date of Birth: 25-3-1990

				
			

Array of Structures

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 <stdio.h>

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;
}

				
			

Explanation:

  • Here, we define a structure named employee to represent employee data with members name, emp_id, and salary.
  • We create an array employees of size 3, where each element is of type struct employee.
  • We initialize the array elements with employee data using the curly braces {} syntax.
  • We then loop through the array and print the details of each employee.
				
					// 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

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 <stdio.h>

// 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;
}

				
			

Explanation:

  • We define a structure student with three members: roll_number, name, and marks.
  • We declare a function displayStudent that takes a structure of type student as a parameter and displays its details.
  • In the main function, we create a structure variable s1 and initialize it with some values.
  • We then pass this structure variable s1 to the displayStudent function, where its details are printed.
				
					// output //
Roll Number: 1
Name: John
Marks: 95.50

				
			

Definition of a Union

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.

Basic Concepts of Unions

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...
};
				
			

Memory Allocation

Unlike structures, unions allocate memory only for the largest member. This is because all members share the same memory location.

Accessing Union Members

Union members are accessed using the dot (.) operator, similar to structures.

Let’s dive into some examples to understand unions better.

				
					#include <stdio.h>

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.

Union with Structure

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 <stdio.h>

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

				
			

Nested Unions

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 <stdio.h>

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.

Union with Bit Fields

Unions can also be used with bit fields to create compact data structures where individual bits represent specific flags or attributes.

				
					#include <stdio.h>

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.

Union and Type Punning

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 <stdio.h>

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.

Explanation:

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! ❤️

Table of Contents