Structures and Unions in C Programming: Syntax, Uses and Complete Guide with Examples

What is Structures and Unions in C Programming: Syntax, Uses and Complete Guide with Examples

Chapter 15: Structures and Unions

Previous Chapter | Current Chapter: Structures and Unions | Next Chapter ➜

Author: Er. Mujtaba Ansari

Want to organize different types of data in C? Structures and Unions make it simple, organized, and memory-efficient.

Real-Life Benefits
  • 🎓 Manage student records
  • 🛒 Manage product information
  • 🏦 Store banking details
  • 🏥 Organize patient records
  • 💾 Use memory efficiently
  • ⚙️ Build system and embedded applications

Structures and Unions in C Programming: Complete Guide with Examples

When a C program becomes larger, working with individual variables can quickly become difficult. Imagine storing the details of a student: their roll number, name, marks, course, and contact information. Creating separate variables for every piece of information works, but it is not an efficient way to organize related data.

This is where Structures and Unions in C Programming become useful.

A Structure allows you to combine different types of related data under one name, while a Union allows multiple members to share the same memory location.

In this guide or article, you will learn Structure and Union in C from the basics, including syntax, declaration, initialization, arrays, functions, nested structures, memory allocation, typedef, enum, practical programs, and the difference between Structure and Union.

A Structure in C is a user-defined data type that allows you to group multiple variables, even when they have different data types, under a single name.

For example, consider a student record:

  • Roll Number → int
  • Name → char
  • Marks → float

Instead of maintaining these values as unrelated variables, we can combine them into one Student structure.

Very Simple Definition

A structure is a user-defined data type used to group related variables of different or similar data types into a single unit.

The general syntax of a structure is:

struct structure_name
{
    data_type member1;
    data_type member2;
    data_type member3;
};

For example:

struct Book
{
    int code;
    char title[30];
    char author[20];
    float price;
};

Here, Book is the structure name, while code, title, author, and price are its members.

Once a structure has been defined, we can create variables of that structure.

Method 1: Declare variables with the structure definition

struct Book
{
    int code;
    char title[30];
    char author[20];
    float price;
} book1, book2;

Here, book1 and book2 are structure variables.

Method 2: Declare the variable separately

struct Book book1;

This approach is useful when you want to define the structure first and create variables later.

The dot (.) operator is used to access members of a structure variable.

For example:

book1.code = 101;
book1.price = 499.50;

Here:

book1.code

means that we are accessing the code member of the book1 structure variable.

Similarly:

book1.price

accesses the price member.

A structure can be initialized when its variable is declared.

#include <stdio.h>

struct Student
{
    int roll;
    char name[20];
    float marks;
};

int main()
{
    struct Student student = {101, "Rahul", 89.5};

    printf("Roll Number: %d\n", student.roll);
    printf("Name: %s\n", student.name);
    printf("Marks: %.2f\n", student.marks);

    return 0;
}

The values are assigned to the members in the same order in which they are declared.

One important characteristic of a structure is that its members have their own storage within the structure object.

For example:

struct Student
{
    int roll;
    char name[20];
    float marks;
};

The structure contains storage for roll, name, and marks.

However, the total size of a structure is not always simply the sum of the sizes of its members. The compiler may add padding for memory alignment.

You can check the actual size using:

printf("%zu", sizeof(struct Student));

The exact size can therefore depend on the compiler and target system.

An array can be used as a member of a structure. This is useful when one record contains multiple values of the same type.

For example, a student may have marks in three subjects:

struct Student
{
    int roll;
    char name[20];
    int marks[3];
};

Here, marks[3] is an array inside the Student structure.

The individual marks can be accessed using:

student.marks[0];
student.marks[1];
student.marks[2];

Suppose you need to store information for 5 students.

Creating five separate structure variables would work, but an array of structures provides a much cleaner solution.

struct Student
{
    int roll;
    char name[20];
    int marks[3];
};

struct Student students[5];

Now, students can hold five Student records.

For example:

students[0]
students[1]
students[2]
students[3]
students[4]

represent five different students.

#include <stdio.h>

struct Student
{
    int roll;
    char name[20];
    int marks[3];
};

int main()
{
    struct Student students[5];
    int i, j;

    for (i = 0; i < 5; i++)
    {
        printf("\nEnter details for Student %d\n", i + 1);

        printf("Roll Number: ");
        scanf("%d", &students[i].roll);

        printf("Name: ");
        scanf("%19s", students[i].name);

        for (j = 0; j < 3; j++)
        {
            printf("Marks in Subject %d: ", j + 1);
            scanf("%d", &students[i].marks[j]);
        }
    }

    printf("\n--- Student Records ---\n");

    for (i = 0; i < 5; i++)
    {
        printf("\nStudent %d\n", i + 1);
        printf("Roll Number: %d\n", students[i].roll);
        printf("Name: %s\n", students[i].name);

        for (j = 0; j < 3; j++)
        {
            printf("Subject %d: %d\n",
                   j + 1, students[i].marks[j]);
        }
    }

    return 0;
}

This type of approach is commonly useful when a program needs to manage multiple records.

Structures can also be used with functions in several ways.

A structure can be:

  • Passed to a function as an argument
  • Passed through a pointer
  • Returned from a function

This makes structures particularly useful for organizing larger programs.

Passing a Structure to a Function

#include <stdio.h>

struct Student
{
    int roll;
    float marks;
};

void display(struct Student student)
{
    printf("Roll Number: %d\n", student.roll);
    printf("Marks: %.2f\n", student.marks);
}

int main()
{
    struct Student student = {101, 92.5};

    display(student);

    return 0;
}

Here, the complete structure variable is passed to the display() function.

A function can also return a structure.

A good example is adding two complex numbers.

A complex number contains two parts:

  • Real part
  • Imaginary part

We can represent both using a structure.

#include <stdio.h>

struct Complex
{
    float real;
    float imag;
};

struct Complex add(struct Complex a, struct Complex b)
{
    struct Complex result;

    result.real = a.real + b.real;
    result.imag = a.imag + b.imag;

    return result;
}

int main()
{
    struct Complex first, second, result;

    printf("Enter first complex number: ");
    scanf("%f %f", &first.real, &first.imag);

    printf("Enter second complex number: ");
    scanf("%f %f", &second.real, &second.imag);

    result = add(first, second);

    printf("Result = %.2f + %.2fi\n",
           result.real, result.imag);

    return 0;
}

The add() function receives two structures and returns another structure containing the result.

Structures can also make mathematical programs easier to organize.

For two complex numbers:

(a + bi) × (c + di)

the result is:

(ac - bd) + (ad + bc)i

A corresponding function can be written as:

struct Complex multiply(struct Complex a, struct Complex b)
{
    struct Complex result;

    result.real = a.real * b.real - a.imag * b.imag;
    result.imag = a.real * b.imag + a.imag * b.real;

    return result;
}

Structures are also useful for representing values that naturally contain multiple related fields.

For example, time can be represented using:

  • Hours
  • Minutes
  • Seconds
#include <stdio.h>

struct Time
{
    int hours;
    int minutes;
    int seconds;
};

struct Time addTime(struct Time a, struct Time b)
{
    struct Time result;

    result.seconds = a.seconds + b.seconds;
    result.minutes = a.minutes + b.minutes;
    result.hours = a.hours + b.hours;

    if (result.seconds >= 60)
    {
        result.minutes += result.seconds / 60;
        result.seconds %= 60;
    }

    if (result.minutes >= 60)
    {
        result.hours += result.minutes / 60;
        result.minutes %= 60;
    }

    return result;
}

int main()
{
    struct Time first, second, result;

    printf("Enter first time (HH MM SS): ");
    scanf("%d %d %d",
          &first.hours,
          &first.minutes,
          &first.seconds);

    printf("Enter second time (HH MM SS): ");
    scanf("%d %d %d",
          &second.hours,
          &second.minutes,
          &second.seconds);

    result = addTime(first, second);

    printf("Result = %02d:%02d:%02d\n",
           result.hours,
           result.minutes,
           result.seconds);

    return 0;
}

A Nested Structure means using one structure as a member of another structure.

This is useful when a real-world object contains another logical group of information.

For example, an employee can have an address:

struct Address
{
    char city[30];
    int pin;
};

struct Employee
{
    int id;
    char name[30];
    struct Address address;
};

Now we can access the city using:

employee.address.city

and the PIN code using:

employee.address.pin
#include <stdio.h>

struct Address
{
    char city[30];
    int pin;
};

struct Employee
{
    int id;
    char name[30];
    struct Address address;
};

int main()
{
    struct Employee employee =
    {
        101,
        "Amit",
        {"Delhi", 110001}
    };

    printf("Employee ID: %d\n", employee.id);
    printf("Name: %s\n", employee.name);
    printf("City: %s\n", employee.address.city);
    printf("PIN Code: %d\n", employee.address.pin);

    return 0;
}

This approach makes complex information easier to organize.

A Union in C is another user-defined data type that allows different members to share the same memory location.

The syntax of a union looks similar to a structure:

union union_name
{
    data_type member1;
    data_type member2;
    data_type member3;
};

For example:

union Data
{
    int number;
    float price;
    char name[20];
};

The important difference is how memory is used.

In a structure, each member has its own storage within the object.

In a union, all members overlap and share the same storage.

Consider:

union Data
{
    int number;
    float price;
};

If we write:

union Data data;

data.number = 100;

the shared storage contains the representation of 100 as an integer.

If we then write:

data.price = 25.5;

the same storage is used for the float value.

Therefore, writing one member can replace the value previously stored through another member.

This is why unions are useful when different representations occupy the same logical storage, but are not required simultaneously.

#include <stdio.h>

union Data
{
    int number;
    float price;
};

int main()
{
    union Data data;

    data.number = 100;

    printf("Number: %d\n", data.number);

    data.price = 25.5;

    printf("Price: %.2f\n", data.price);

    return 0;
}

The program demonstrates that both members use the same storage area.

Understanding the difference between Structure and Union is very important.

FeatureStructureUnion
MemoryMembers occupy separate storage within the objectMembers share the same storage
ValuesMultiple members can hold values simultaneouslyTypically one member’s stored representation is used at a time
SizeDepends on members plus possible paddingLarge enough for its largest member, subject to alignment
Main PurposeGroup related dataShare storage between alternative data representations
Member Access. or ->. or ->
Easy Way to Remember for YOU

Structure = Separate storage for members

Union = Shared storage for members

Consider the following Structure:

struct Data
{
    int a;
    float b;
    char c;
};

Each member has its own location within the structure object, although the compiler may insert padding.

Now consider:

union Data
{
    int a;
    float b;
    char c;
};

All three members overlap in the same storage area.

This is the fundamental memory difference between a Structure and a Union.

The typedef keyword is used to create an alias for an existing data type.

Instead of repeatedly writing a longer type name, you can define a shorter, more convenient name.

Syntax
typedef existing_type new_name;

Example:

typedef int Integer;

Now:

Integer number;

is equivalent to:

int number;

typedef does not create a completely new primitive type; it creates another name for an existing type.

typedef is frequently used with structures to make declarations cleaner.

typedef struct
{
    int roll;
    char name[20];
    float marks;
} Student;

Now we can simply write:

Student student1;

instead of:

struct Student student1;
#include <stdio.h>

typedef struct
{
    int roll;
    char name[20];
    float marks;
} Student;

int main()
{
    Student student = {101, "Rahul", 88.5};

    printf("Roll Number: %d\n", student.roll);
    printf("Name: %s\n", student.name);
    printf("Marks: %.2f\n", student.marks);

    return 0;
}

enum, short for enumeration, is a user-defined type used to define a set of named integer constants.

Syntax
enum enum_name
{
    constant1,
    constant2,
    constant3
};

For example:

enum Color
{
    Black,
    Red,
    Blue,
    Green
};

By default, enumeration constants start at 0.

Therefore:

Black = 0
Red   = 1
Blue  = 2
Green = 3

You can also explicitly assign values.

enum Color
{
    Black,
    Red,
    Blue = 5,
    Green
};

The values become:

Black = 0
Red   = 1
Blue  = 5
Green = 6

After an explicitly assigned value, subsequent enumerators continue from that value.

#include <stdio.h>

enum Status
{
    FALSE,
    TRUE
};

int main()
{
    enum Status result = TRUE;

    printf("Status: %d\n", result);

    return 0;
}

Output:

Status: 1

Named constants can make code easier to understand compared with using unexplained numeric values.

Structures are also frequently used with pointers.

Suppose we have:

struct Student
{
    int roll;
    float marks;
};

and:

struct Student student;
struct Student *ptr = &student;

A member can be accessed through the pointer using the arrow (->) operator:

ptr->roll = 101;
ptr->marks = 90.5;

This is equivalent to:

(*ptr).roll = 101;
(*ptr).marks = 90.5;

Understanding this becomes particularly important when learning Structures with Pointers and Dynamic Memory Allocation.

Structures and Unions are not limited to classroom programs. They are useful for representing data in many types of software.

1. Student Management Systems

A Student structure can contain:

Roll Number
Name
Course
Marks
Contact Details

2. Banking Applications

A customer or account record can contain:

Account Number
Customer Name
Balance
Account Type

3. E-Commerce Systems

Product information can be represented using:

Product ID
Product Name
Price
Quantity
Category

4. Employee Management

An employee record can contain:

Employee ID
Name
Salary
Department
Address

5. Hospital Management

Patient information can be grouped into a single structure:

Patient ID
Name
Age
Doctor
Medical Record Information

6. Games and Applications

A game can use structures to represent player information such as:

Player Name
Score
Level
Position
Health

7. Embedded and System Programming

Unions can be useful when a program needs to represent alternative data formats while sharing storage. Structures are also widely useful for organizing groups of fields that represent system or hardware-related data.

Structures and Unions are important because they introduce a more organized way of handling data.

By learning them, you can:

  • Build programs around real-world objects.
  • Group related information together.
  • Manage multiple records efficiently.
  • Work with arrays of complex records.
  • Pass structured data to functions.
  • Return structured results from functions.
  • Build nested data models.
  • Understand shared memory through unions.
  • Write cleaner code using typedef.
  • Represent named constants using enum.
  • Prepare for advanced concepts such as pointers and dynamic memory.

1. Forgetting the semicolon

A structure definition must end with a semicolon:

struct Student
{
    int roll;
};

2. Using the wrong member access operator

For a normal structure variable:

student.roll

For a pointer to a structure:

studentPtr->roll

3. Assuming Union members have separate storage

They do not. Union members share the same storage.

4. Using unsafe gets()

Older C examples often contain:

gets(name);

You should avoid gets() because it cannot safely limit the amount of input read. Modern C programs should use safer input techniques such as fgets() where appropriate.

5. Assuming sizeof(struct) is always the sum of member sizes

Compiler-added padding and alignment can make the actual structure size larger than the simple sum.

ConceptDescription
StructureGroups related data into one type
Structure MemberVariable declared inside a structure
. OperatorAccesses a member through a structure object
-> OperatorAccesses a member through a structure pointer
Array of StructuresStores multiple structure records
Nested StructureStructure used inside another structure
UnionMembers share the same storage
typedefCreates an alias for an existing type
enumDefines named integer constants

Structures and Unions in C Programming provide an important way to organize and manage data beyond simple variables and arrays.

A Structure is particularly useful when several related values need to exist together, even when those values have different data types. An array of structures can then be used to manage multiple records, while nested structures help model more complex relationships.

A Union follows a different memory model: its members share storage. This makes it useful when different data representations need to occupy the same memory area.

Along with typedef and enum, these concepts form an important part of C’s user-defined data type system and provide a strong foundation for more advanced topics such as Pointers, Dynamic Memory Allocation, File Handling, and Data Structures.

What is a Structure in C?

A Structure is a user-defined data type that groups related variables, including variables of different data types, under one name.

What is a Union in C?

A Union is a user-defined data type in which all members share the same storage area.

What is the main difference between Structure and Union?

The main difference is memory organization. Structure members have separate storage within the object, while Union members share the same storage.

Can a Structure contain an Array?

Yes. An array can be declared as a member of a Structure.

Can a Structure be passed to a function?

Yes. A Structure can be passed to a function by value or through a pointer.

Can a function return a Structure?

Yes. A function can return a structure value.

What is a Nested Structure?

A Nested Structure is a structure that contains another structure as one of its members.

What is the use of typedef in C?

typedef creates an alias for an existing data type, making declarations easier to read and write.

What is enum in C?

enum is used to define a set of named integer constants.

Which operator is used to access Structure members?

The dot (.) operator is used with a structure object, while the arrow (->) operator is used with a pointer to a structure.



Leave a Comment

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

Scroll to Top