In the C programming language, a structure is a user-defined data type that allows grouping variables of different data types under a single name. This feature is especially useful for modeling real-world entities. For example, a student can have properties such as roll number, name, and marks, all of which can be stored together using a structure. Unlike arrays that store multiple elements of the same data type, structures store elements of different data types, which is why they are called heterogeneous collections.
Structures help in organizing complex data in a program. With the struct keyword, a programmer can define a new data type that can hold multiple pieces of related information. This leads to cleaner, more modular, and maintainable code. Since C does not support object-oriented programming natively, structures play a vital role in bridging that gap by enabling the encapsulation of data.
The structure creates a template for a complex data type and makes it possible to create variables of that type. Each variable that is declared using the structure type will contain all the members defined within the structure.
Syntax of Structure in C
The basic syntax of a structure begins with the keyword struct followed by a structure name. Inside the curly braces, members are declared using standard C data types. These members can be of any valid C type, including other structures or arrays.
Here is the general syntax:
c
CopyEdit
struct structure_name
{
data_type member1;
data_type member2;
…
};
After the closing curly brace, it is possible to declare structure variables directly by specifying variable names. This eliminates the need to separately declare structure variables later in the code.
Declaring and Using Structure Variables
There are two common ways to declare structure variables in C. The first is to declare the variable when defining the structure, and the second is to declare it separately inside a function, such as main.
In the first method, the structure variable is declared immediately after the structure definition:
c
CopyEdit
struct student
{
int rollno;
char name[60];
}s1;
In this example, a structure called student is defined with two members: an integer rollno and a character array name. A structure variable s1 is declared at the end of the definition. This variable can be used throughout the program to access the members.
In the second method, the variable is declared separately inside the main function or any other function:
c
CopyEdit
struct student s1;
In both cases, the structure members can be accessed using the dot operator. For example, s1.rollno refers to the roll number, and s1.name refers to the name.
Structure Example with Explanation
Below is a complete example demonstrating the declaration, assignment, and usage of a structure in C:
c
CopyEdit
#include <stdio.h>
#include <string.h>
struct student
{
int rollno;
char name[60];
}s1;
void main()
{
s1.rollno = 1;
strcpy(s1.name, “intellipaat”);
printf(“Rollno : %d\n”, s1.rollno);
printf(“Name : %s\n”, s1.name);
}
In this program, a structure called student is created with two members: rollno and name. A variable s1 of type struct student is declared. Inside the main function, the roll number is assigned the value 1, and the name is copied using the strcpy function. The printf function is then used to display the roll number and name.
This example highlights several important points. First, it shows how structure members are accessed using the dot operator. Second, it demonstrates how character arrays are initialized using the strcpy function, since direct assignment is not possible for arrays in C. Third, it reinforces how structure variables behave like regular variables in terms of assignment and access.
Why Use Structures in C
Structures are essential for grouping logically related data. Without structures, programmers would need to manage several independent variables, making the code harder to read, maintain, and debug. For example, managing data for 100 students would be extremely difficult if each student’s name, roll number, and other details were stored in separate arrays.
Structures make it possible to define a single variable that contains all necessary fields. This enables more complex data operations such as sorting, searching, and storing data in files. Structures also make it easier to pass related data between functions as a single argument, which leads to cleaner function signatures and less overhead in function calls.
Furthermore, structures support array usage, which allows the creation of an array of structures. This is helpful when working with collections of similar data. For instance, an array of student structures allows storing data for multiple students in a single variable.
Memory Allocation for Structures
Each member of a structure is allocated memory based on its data type. The total size of a structure is the sum of the sizes of its members, possibly with some additional padding bytes inserted by the compiler to maintain alignment. Alignment is a concept where variables are stored in memory at addresses that are multiples of their size, which improves performance on most hardware platforms.
Consider this structure:
c
CopyEdit
struct sample
{
int a;
char b;
float c;
};
Assuming int takes 4 bytes, char takes 1 byte, and float takes 4 bytes, the structure may require more than 9 bytes in total. Due to alignment, padding may be added between members. For example, after the char member b, 3 bytes may be inserted to align the float member c on a 4-byte boundary. The actual memory consumed by the structure would be 12 bytes in that case.
This is important to consider when dealing with memory-sensitive applications. Tools like sizeof can be used to determine the memory used by a structure.
Arrays Within Structures
Structures can contain arrays as their members. This is useful when a group of values needs to be stored together, such as a name or a list of scores. For example, a structure containing a character array allows storing a string:
c
CopyEdit
struct student
{
int rollno;
char name[50];
};
The name array can store a string of characters, and functions like strcpy and strlen can be used to manipulate it. Care must be taken to ensure that the array is large enough to hold the desired string, including the null terminator.
Arrays of structures are also commonly used when storing multiple records. An array of student structures allows managing several students at once using a loop. Each element in the array is a structure, and its members can be accessed using the dot operator and array indexing.
Structures as Function Arguments
Structures can be passed to functions as arguments either by value or by reference. When passed by value, a copy of the structure is created and passed to the function. Any changes made to the structure within the function do not affect the original structure. This can lead to performance overhead if the structure is large.
Passing structures by reference, on the other hand, involves passing a pointer to the structure. This is more efficient and allows the function to modify the original structure. Here’s an example:
c
CopyEdit
void display(struct student s)
{
printf(“Rollno: %d\n”, s.rollno);
printf(“Name: %s\n”, s.name);
}
To pass by reference:
c
CopyEdit
void modify(struct student *s)
{
s->rollno = 2;
strcpy(s->name, “updated”);
}
In this case, the arrow operator is used to access members of the structure through the pointer.
Understanding these techniques is crucial for designing efficient and maintainable programs, especially when working with large data structures or when memory optimization is important.
Introduction to Unions in C
A union is a special data type in C, similar to a structure, but with a key difference in memory allocation. While structures allocate separate memory for each member, a union uses a single shared memory location for all its members. This means only one member can contain a value at any given time, and updating one member overwrites the others.
Unions are useful when a variable may hold different data types at different times. For example, when designing a compiler or interpreter, a union can be used to store different kinds of tokens such as integers, floats, or characters. Since only one token type is needed at a time, using a union conserves memory.
Unions provide an efficient way to use memory when working with variables that are mutually exclusive in usage. However, careful attention must be paid when using unions to avoid overwriting values unintentionally.
Syntax of Union in C
The syntax of a union is very similar to that of a structure. The only difference is the use of the union keyword instead of struct.
c
CopyEdit
union union_name
{
data_type member1;
data_type member2;
…
};
Union variables can be declared directly after the closing brace or separately inside a function.
Example:
c
CopyEdit
union student
{
int rollno;
char name[60];
} s1;
In this example, s1 is a variable of the union student. It can either store an integer in rollno or a string in name, but not both at the same time.
Memory Allocation in Unions
Unlike structures, where each member has its own memory space, unions allocate only the memory required for the largest member. This means all members share the same memory location.
Consider the following union:
c
CopyEdit
union data
{
int a; // 4 bytes
float b; // 4 bytes
char str[20]; // 20 bytes
};
The total memory allocated for this union is 20 bytes, which is the size of the largest member (str). If a value is assigned to str, it will occupy the entire memory, and assigning a value to a or b afterward will overwrite the contents of str.
Understanding how memory is shared among members is crucial when working with unions to avoid data corruption.
Accessing Union Members
Union members are accessed using the dot (.) operator, similar to structures. However, only one member should be used at a time.
Example:
c
CopyEdit
#include <stdio.h>
#include <string.h>
union student
{
int rollno;
char name[60];
} s1;
void main()
{
s1.rollno = 1;
printf(“Rollno: %d\n”, s1.rollno);
strcpy(s1.name, “intellipaat”);
printf(“Name: %s\n”, s1.name);
}
In this example, although both rollno and name are accessed, only the last assigned member (name) will have valid data. Assigning to name overwrites the data stored in rollno.
Structures are more suitable when storing related but distinct pieces of information together, like in a record. Unions are ideal when optimizing memory, and only one piece of data is needed at a time.
Practical Use Cases of Unions
Unions are widely used in embedded systems, low-level programming, and applications where memory efficiency is critical. Some practical examples include:
- Type conversion: Unions can store a value in one data type and interpret it as another.
- Embedded systems: To store sensor data where only one type of reading is needed at a time.
- Variant data types: Used in compilers or interpreters to store different kinds of tokens.
- Networking protocols: To store different packet formats in the same memory space.
Here’s an example of using a union for type conversion:
c
CopyEdit
union value
{
int i;
float f;
};
union value v;
v.i = 1065353216;
printf(“As float: %f\n”, v.f); // Interprets the integer bits as a float
Advanced Topics in Structures and Unions
After understanding the basics of structures and unions, it’s useful to explore some of the more advanced features available in C. These include nested structures, arrays of structures, pointers to structures, and the use of typedef with structures and unions.
These features allow more flexible and powerful use of user-defined data types, and they are especially useful in building large-scale software systems.
Nested Structures in C
A nested structure is a structure that contains another structure as one of its members. This allows modeling complex relationships between data types.
Syntax:
c
CopyEdit
struct address
{
char city[20];
int pin;
};
struct student
{
int rollno;
char name[50];
struct address addr;
};
In the example above, the student structure includes another structure address as one of its members. This makes it easier to group related data while keeping the main structure organized.
Accessing Nested Structure Members:
c
CopyEdit
struct student s1;
strcpy(s1.addr.city, “Delhi”);
s1.addr.pin = 110001;
Use the dot operator (.) to access nested members. Each level is accessed using the respective structure name.
Array of Structures
An array of structures is used to store a list of records, each containing multiple data fields. This is commonly used to store information such as a list of students, employees, products, etc.
Example:
c
CopyEdit
struct student
{
int rollno;
char name[50];
};
struct student s[3];
You can access individual records and their fields using array indexing and the dot operator:
c
CopyEdit
s[0].rollno = 1;
strcpy(s[0].name, “John”);
s[1].rollno = 2;
strcpy(s[1].name, “Alice”);
Looping through arrays of structures makes it easy to process records in bulk.
Pointer to Structure
Pointers to structures allow dynamic access to structure members and are widely used in real-world C programming. This is especially helpful in functions that modify structured data or in dynamic memory allocation scenarios.
Declaring a Pointer to a Structure:
c
CopyEdit
struct student
{
int rollno;
char name[50];
};
struct student s1;
struct student *ptr;
ptr = &s1;
Accessing Members Using Pointer:
Use the arrow operator (->) to access members via a pointer:
c
CopyEdit
ptr->rollno = 10;
strcpy(ptr->name, “David”);
This is equivalent to:
c
CopyEdit
(*ptr).rollno = 10;
Using pointers to structures is common when working with linked lists, trees, or dynamic data.
Typedef with Structures and Unions
The typedef keyword is used to create an alias for a data type, making the code cleaner and easier to understand. It’s particularly useful when working with complex data types like structures and unions.
Example with Structure:
c
CopyEdit
typedef struct student
{
int rollno;
char name[50];
} Student;
Now, instead of using struct student, you can simply use Student to declare variables:
c
CopyEdit
Student s1;
Example with Union:
c
CopyEdit
typedef union data
{
int i;
float f;
} Data;
Data d1;
This technique is widely used in large programs for readability and maintainability.
Self-referential Structures
A self-referential structure is a structure that contains a pointer to a structure of the same type. These are commonly used to create data structures like linked lists, trees, and graphs.
Example:
c
CopyEdit
struct node
{
int data;
struct node *next;
};
Each node in the list contains data and a pointer to the next node, enabling dynamic data structures. This forms the basis for many advanced algorithms and is a fundamental concept in data structures.
Union Within a Structure
Unions can also be nested inside structures when certain data fields are mutually exclusive but still part of the same record. This helps save memory.
Example:
c
CopyEdit
struct item
{
int type;
union
{
int int_val;
float float_val;
char str[20];
} value;
};
Depending on the type, only one of the union members is used. This technique is useful in parsers, interpreters, or when working with variant records.
Bit Fields in Structures
Bit fields allow the allocation of a specific number of bits to structure members. This is useful when memory optimization is critical, such as in embedded systems.
Example:
c
CopyEdit
struct flags
{
unsigned int isVisible: 1;
unsigned int isEnabled 1;
unsigned int isChecked: 1;
};
Here, only 3 bits are used for all members, which saves space compared to using full integers for each flag.
Practice Problems on Structures and Unions in C
Solving problems is the best way to strengthen your understanding. Below are some practical programming exercises focused on structures and unions.
Problem 1: Structure to Store and Display Student Details
Task:
Define a structure to store student details: roll number, name, and marks in three subjects. Write a program to input and display the details of 3 students.
Hint:
Use an array of structures and loop through it.
Problem 2: Structure with Nested Structure
Task:
Create a structure Student that contains another structure Address with fields city and pin code. Input and display the student’s name and address.
Problem 3: Union for Type Conversion
Task:
Declare a union with an integer and a float. Assign a value to the integer and display it as a float. Observe the result and explain why it happens.
Problem 4: Pass Structure to Function
Task:
Create a structured Book with title, author, and price. Write a function that accepts a structure as an argument and displays its details.
Problem 5: Use Typedef with Structure
Task:
Use typedef to define a new name for a structure Employee that contains id, name, and salary. Declare and initialize one variable using the new type name.
Problem 6: Pointer to Structure
Task:
Write a program using a pointer to a structure that inputs and displays employee details using dynamic memory allocation (use malloc).
Real-world Applications of Structures and Unions
Structures and unions are foundational in building real-life software systems, especially in systems programming, embedded systems, and file handling.
Application 1: Database Systems
Structures are used to represent records like employees, students, or customers. Arrays of structures can store large datasets in memory for processing.
Application 2: Embedded Systems
Unions and bit fields are widely used in embedded software to conserve memory. Device drivers use unions to map hardware registers.
Application 3: Compilers and Interpreters
Unions are used to store tokens with different data types such as integers, floats, and strings. Structures with unions allow creating syntax trees and symbol tables.
Application 4: Network Programming
Structures represent packets, headers, and frames. Bit fields can define individual flags in a packet, and unions allow interpreting the same data in multiple ways.
Application 5: Graphics and Gaming
Structures are used to define points, colors, shapes, and game objects. Nesting structures help manage complex scenes.
Final Thoughts
Understanding structures and unions in C is essential for mastering data organization, memory management, and low-level programming. These user-defined data types allow you to group different kinds of data into a single unit, making your code cleaner, more modular, and easier to maintain.
- Structures are ideal when you need to store multiple related variables and access them all independently.
- Unions are best suited for scenarios where memory efficiency is critical and only one member is used at a time.
In more advanced programming—like embedded systems, compilers, and operating systems—structures and unions form the backbone of custom data representations and efficient memory access.
By learning how to:
- Create and access nested structures
- Work with arrays and pointers to structures
. - Use unions for overlapping data representations.
- Apply typedef, bit fields, and self-referential structure.s
You’re building a strong foundation for solving real-world problems and acing technical interviews.
As you continue your journey in C programming, regularly apply these concepts through practical projects, exercises, and system-level programming challenges. Mastery of structures and unions not only improves your C skills but also prepares you for learning more advanced topics like data structures, memory management, and systems design.