Back to C Programming
2026-07-115 min read

Store Data in Structures Dynamically

Learn Store Data in Structures Dynamically step by step with clear examples and exercises.

Why This Matters

In programming, structures (often abbreviated as struct) are user-defined data types that allow you to combine and organize multiple data items of different kinds. They play a crucial role in real-world applications where handling complex data sets is essential. Understanding how to work with structures dynamically can help you solve problems more efficiently, improve code readability, and prepare for interviews or exams.

Prerequisites

Before diving into the core concept of storing data in structures dynamically, it's important that you have a good understanding of:

  1. Basic C programming concepts (variables, operators, control statements, etc.)
  2. Arrays and pointers
  3. Functions and function prototypes
  4. File I/O using standard library functions

Core Concept

Defining Structures

A structure is defined using the struct keyword followed by a tag name and enclosed within curly braces {}. Each data item (member) in the structure is declared with its own type.

struct Student {
int roll_number;
char name[50];
float marks;
};

In this example, we have defined a structure called Student, which includes three members: roll_number, name, and marks.

Allocating Memory for Structures Dynamically

To allocate memory for structures dynamically, you can use the malloc() function. This allows you to create an array of structures with a variable number of elements at runtime.

struct Student* create_students(int num_students) {
struct Student *students = (struct Student *) malloc(num_students * sizeof(struct Student));
if (!students) {
printf("Memory allocation failed!\n");
exit(EXIT_FAILURE);
}
return students;
}

In the above code, we have created a function called create_students(), which takes an integer argument representing the number of students and returns a pointer to an array of Student structures. The memory for this array is allocated using malloc().

Accessing and Modifying Structure Members

To access or modify a structure member, you can use the dot operator (.) or the arrow operator (->). The choice between them depends on whether you have a pointer to the structure.

struct Student student = {1, "John Doe", 85.5};
// Accessing members using the dot operator
printf("Student roll number: %d\n", student.roll_number);

// Using a pointer and the arrow operator
struct Student *ptr_student = &student;
printf("Student name: %s\n", ptr_student->name);

Freeing Memory

When you're done using a dynamically allocated structure, it's essential to free its memory to avoid memory leaks. You can use the free() function for this purpose.

void free_students(struct Student *students, int num_students) {
if (students != NULL) {
free(students);
}
}

In this example, we have created a function called free_students(), which takes a pointer to the array of structures and its size. The memory for the entire array is freed using free().

Worked Example

This program asks how many student records are needed, allocates exactly that

many Student objects, reads each record safely, prints the records, and then

releases the single allocated block. Keeping the ownership model simple makes

the example suitable for extending later.

#include <stdio.h>
#include <stdlib.h>

struct Student {
int roll_number;
char name[50];
float marks;
};

static float calculate_average(const struct Student *students, size_t count) {
float total = 0.0f;
for (size_t i = 0; i < count; ++i) {
total += students[i].marks;
}
return total / (float)count;
}

int main(void) {
size_t count;
printf("Number of students: ");
if (scanf("%zu", &count) != 1 || count == 0) {
fprintf(stderr, "Enter a positive number.\n");
return EXIT_FAILURE;
}

struct Student *students = malloc(count * sizeof *students);
if (students == NULL) {
perror("malloc");
return EXIT_FAILURE;
}

for (size_t i = 0; i < count; ++i) {
printf("Roll number, name, and marks for student %zu: ", i + 1);
if (scanf("%d %49s %f",
&students[i].roll_number,
students[i].name,
&students[i].marks) != 3) {
fprintf(stderr, "Invalid student record.\n");
free(students);
return EXIT_FAILURE;
}
}

for (size_t i = 0; i < count; ++i) {
printf("%d %-20s %.2f\n",
students[i].roll_number,
students[i].name,
students[i].marks);
}

printf("Average marks: %.2f\n", calculate_average(students, count));
free(students);
return EXIT_SUCCESS;
}

count is validated before multiplication, so the program never deliberately

requests a zero-sized array. sizeof *students follows the pointer's type and

stays correct if the structure type changes. The width limit in %49s leaves

room for the terminating null character in name. If any input operation

fails, the program frees the owned block before returning. Because all

students occupy one contiguous allocation, exactly one successful malloc

requires exactly one final free.

Common Mistakes

  1. Forgetting to check if memory allocation was successful before using the allocated memory.
  2. Accessing or modifying structure members with an incorrect pointer or index.
  3. Failing to free dynamically allocated memory when it's no longer needed, leading to a memory leak.
  4. Not handling errors (e.g., file not found) properly in the program.
  5. Using scanf() without specifying appropriate format characters for each data item, which can lead to incorrect data being read.

Practice Questions

  1. Write a function that sorts an array of structures based on the roll number of students.
  2. Modify the example program to also display the name and roll number of each student with their marks.
  3. Implement a function that adds a new student at the end of the dynamically allocated structure array.
  4. Write a function that finds the student with the highest marks in the structure array.
  5. Implement a function that merges two sorted arrays of structures.

FAQ

What happens if I forget to free dynamically allocated memory?

Memory remains allocated until the process exits. Repeated leaks make a

long-running program consume progressively more memory and may eventually

cause allocation failures.

Can I create a dynamic array of structures?

Yes. Allocate count * sizeof *pointer bytes and access the elements with

pointer[index], just like an ordinary array.

How do I initialize one dynamically allocated structure?

Allocate it first, verify the returned pointer, and then assign members with

the arrow operator. For example, student->marks = 80.0f; is valid only after

student points to a live Student object.

When should I use the dot operator instead of the arrow operator?

Use . with a structure object, such as students[i].marks. Use -> with a

pointer to a structure, such as student->marks. The expression p->member

is shorthand for (*p).member.

Can a dynamically allocated structure contain pointers?

Yes, but each pointed-to allocation has its own lifetime. Free nested

allocations first, then free the containing structure. A pointer member does

not automatically allocate or release the memory it references.