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

FeatureStructureUnion
MemoryEach member has its own memoryAll members share the same memory
SizeSum of all member sizes (+ padding)Size of the largest member
AccessAll members can be used at same timeOnly one member can be used at a time
Use CaseWhen all fields are needed simultaneouslyWhen 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.

Leave a Comment

Your email address will not be published. Required fields are marked *