So far, we've been working with fixed variables, not allowing users to create different variables according to their needs. Let me illustrate with an example: Imagine you're developing a text encoder. You don't know how much memory space you'll need until the user inputs the text, which could be as short as a word or as lengthy as an entire book. The solution isn't as simple as declaring a rookie `char[10000]`, as we might still run out of space, or end up with excessive memory usage for decoding shorter inputs. We need to dynamically allocate memory and adjust the variables according to runtime conditions. That's the essence of this lesson.
Dynamic memory allocation is the practice of assigning memory locations to variables during program execution, at the explicit request of the programmer. It's a unique feature of C among high-level languages, allowing us to create data types and structures of varying sizes to suit our program's needs.
For instance, when using arrays, dynamic memory allocation eliminates the need to determine the array size at declaration time. We don't have to allocate extra space, anticipating potential needs. For instance, we might anticipate needing up to 1000 elements, but in reality, we're uncertain about the actual usage. Specifying the exact number of elements during declaration can be challenging. Over-allocating memory can lead to wastage, while under-allocating may result in errors when accessing elements beyond the declared size.
Dynamically allocated memory should be explicitly freed when no longer needed. Otherwise, it remains in use, managed by the system (OS). Exiting the program without releasing dynamically allocated memory leads to automatic deallocation. However, it's good practice to explicitly free dynamically allocated memory using dedicated functions.
Dynamically allocated memory resides in a different location from regular variables. It's commonly referred to as the heap, in contrast to the stack where regular variables are allocated. Dynamically allocated variables persist beyond their scope and continue to exist even after the function where they were created has exited.
The functions `malloc()`, `realloc()`, `calloc()`, and `free()`, from the `stdlib.h` library, are responsible for dynamic memory management. All dynamically allocated data resides in the heap, which typically has much larger memory capacity compared to the stack, which is typically limited to 64k at the outset, though this can vary based on the machine.
To dive deeper into memory management in C, you can explore these functions further by clicking on the provided link.
void *malloc(size_t size);
void *calloc(size_t num_elements, size_t element_size);
void *realloc(void *ptr, size_t new_size);
void free(void *ptr);
#include <stdio.h>
#include <stdlib.h>
int main() {
int *ptr;
ptr = (int *)malloc(5 * sizeof(int)); // Allocate memory for 5 integers
if (ptr == NULL) {
printf("Memory allocation failed\n");
return 1;
}
// Use the allocated memory
for (int i = 0; i < 5; i++) {
ptr[i] = i + 1;
}
// Print the values
for (int i = 0; i < 5; i++) {
printf("%d ", ptr[i]);
}
// Deallocate the memory
free(ptr);
return 0;
}
Dynamic memory allocation in C programming provides flexibility and efficiency in managing memory during program execution. By using functions like `malloc()`, `calloc()`, `realloc()`, and `free()`, programmers can allocate and deallocate memory dynamically as needed. However, careful handling of dynamically allocated memory is essential to avoid memory leaks, undefined behavior, and other common pitfalls.