Memory Allocation in C: Static and Dynamic Memory

Learn how memory is allocated in C programming. Discover the differences between static memory (compile-time memory allocation) and dynamic memory (run-time memory allocation), and understand when and how to use them in your C programs.



C Allocate Memory

How Memory is Allocated

When you reserve memory for your variables, that's called memory allocation. The way memory is allocated depends on the type of memory you're working with. In C, there are two main types: static memory and dynamic memory.

Static Memory

Static memory is reserved for variables before your program even starts running, which is why it's also called compile-time memory allocation. This type of memory is automatically allocated when your program is compiled.

For example, if you create an array of integers to hold data for 15 students in a semester, C will reserve enough memory to store 15 elements. If an integer takes up 4 bytes, that means 60 bytes will be set aside:

Syntax

int students[15];
printf("%lu", sizeof(students)); // 60 bytes
Output

60 bytes

But if only 10 students show up, you’ve now wasted memory on 5 extra spaces that aren’t being used. Since you can’t change the size of the array once it’s set, that reserved memory stays unused.

While the program will still run, it might not be as efficient as it could be if you have a lot of similar cases.

Dynamic Memory

Dynamic memory is more flexible because it gets allocated while the program is running, which is why it's called runtime memory allocation. Unlike static memory, you can control exactly how much memory is needed and allocate it as the program runs.

This type of memory isn’t tied to a specific variable. Instead, you access it through pointers. To allocate dynamic memory, you use functions like malloc() and calloc() from the stdlib.h header file.

Syntax

int *ptr1 = malloc(size);
int *ptr2 = calloc(amount, size);

The malloc() function takes one parameter: size, which tells it how many bytes to allocate. calloc() takes two parameters: amount (how many items you need) and size (how big each item is in bytes).

Best Practice: Use sizeof for Memory

It’s a good idea to use the sizeof operator to figure out how much memory you’ll need for a data type:

Syntax

int *ptr1, *ptr2;
ptr1 = malloc(sizeof(*ptr1));
ptr2 = calloc(1, sizeof(*ptr2));

Make sure you use *ptr1 with sizeof. If you forget the * and write sizeof(ptr1), you’ll only get the size of the pointer itself (usually 8 bytes), not the memory you actually want to allocate.

Example: Dynamic Memory for Students

Let’s fix our earlier example of allocating memory for 15 students and instead dynamically allocate memory for the actual 12 students who attend:

Syntax

int *students;
int numStudents = 12;
students = calloc(numStudents, sizeof(*students));
printf("%d", numStudents * sizeof(*students)); // 48 bytes
Output

48 bytes

Now, we’ve only reserved memory for 12 students, so nothing is wasted.

Stack Memory

In addition to static and dynamic memory, there’s another type called stack memory. This is a special kind of dynamic memory that’s used when functions are called. The variables inside a function use stack memory, and it’s automatically freed when the function finishes running.

Stack memory is important to keep in mind, especially when dealing with nested function calls or recursion, as overuse can lead to stack overflow errors.