- C Programming Tutorial
- C - Home
- Basics of C
- C - Overview
- C - Features
- C - History
- C - Environment Setup
- C - Program Structure
- C - Hello World
- C - Compilation Process
- C - Comments
- C - Tokens
- C - Keywords
- C - Identifiers
- C - User Input
- C - Basic Syntax
- C - Data Types
- C - Variables
- C - Integer Promotions
- C - Type Conversion
- C - Type Casting
- C - Booleans
- Constants and Literals in C
- C - Constants
- C - Literals
- C - Escape sequences
- C - Format Specifiers
- Operators in C
- C - Operators
- C - Arithmetic Operators
- C - Relational Operators
- C - Logical Operators
- C - Bitwise Operators
- C - Assignment Operators
- C - Unary Operators
- C - Increment and Decrement Operators
- C - Ternary Operator
- C - sizeof Operator
- C - Operator Precedence
- C - Misc Operators
- Decision Making in C
- C - Decision Making
- C - if statement
- C - if...else statement
- C - nested if statements
- C - switch statement
- C - nested switch statements
- Loops in C
- C - Loops
- C - While loop
- C - For loop
- C - Do...while loop
- C - Nested loop
- C - Infinite loop
- C - Break Statement
- C - Continue Statement
- C - goto Statement
- Functions in C
- C - Functions
- C - Main Function
- C - Function call by Value
- C - Function call by reference
- C - Nested Functions
- C - Variadic Functions
- C - User-Defined Functions
- C - Callback Function
- C - Return Statement
- C - Recursion
- Scope Rules in C
- C - Scope Rules
- C - Static Variables
- C - Global Variables
- Arrays in C
- C - Arrays
- C - Properties of Array
- C - Multi-Dimensional Arrays
- C - Passing Arrays to Function
- C - Return Array from Function
- C - Variable Length Arrays
- Pointers in C
- C - Pointers
- C - Pointers and Arrays
- C - Applications of Pointers
- C - Pointer Arithmetics
- C - Array of Pointers
- C - Pointer to Pointer
- C - Passing Pointers to Functions
- C - Return Pointer from Functions
- C - Function Pointers
- C - Pointer to an Array
- C - Pointers to Structures
- C - Chain of Pointers
- C - Pointer vs Array
- C - Character Pointers and Functions
- C - NULL Pointer
- C - void Pointer
- C - Dangling Pointers
- C - Dereference Pointer
- C - Near, Far and Huge Pointers
- C - Initialization of Pointer Arrays
- C - Pointers vs. Multi-dimensional Arrays
- Strings in C
- C - Strings
- C - Array of Strings
- C - Special Characters
- C Structures and Unions
- C - Structures
- C - Structures and Functions
- C - Arrays of Structures
- C - Self-Referential Structures
- C - Lookup Tables
- C - Dot (.) Operator
- C - Enumeration (or enum)
- C - Structure Padding and Packing
- C - Nested Structures
- C - Anonymous Structure and Union
- C - Unions
- C - Bit Fields
- C - Typedef
- File Handling in C
- C - Input & Output
- C - File I/O (File Handling)
- C Preprocessors
- C - Preprocessors
- C - Pragmas
- C - Preprocessor Operators
- C - Macros
- C - Header Files
- Memory Management in C
- C - Memory Management
- C - Memory Address
- C - Storage Classes
- Miscellaneous Topics
- C - Error Handling
- C - Variable Arguments
- C - Command Execution
- C - Math Functions
- C - Static Keyword
- C - Random Number Generation
- C - Command Line Arguments
- C Programming Resources
- C - Questions & Answers
- C - Quick Guide
- C - Cheat Sheet
- C - Useful Resources
- C - Discussion
Memory Management in C
One of the important characteristics of C is that the compiler manages how the memory is allocated to the variables declared in the code. Once the compiler allocates the required bytes of memory, it cannot be changed during the runtime.
The compiler employs static memory allocation approach. However, there are times where you may need to allocate the memory on demand, during the runtime. Read this chapter to understand how dynamic memory management works in C.
Functions for Dynamic Memory Management in C
The C programming language provides several functions for dynamic memory allocation and management. These functions can be found in the <stdlib.h> header file.
Function | Description |
---|---|
void *calloc(int num, int size); | This function allocates an array of num elements each of which size in bytes will be size. |
void free(void *address); | This function releases a block of memory block specified by address. |
void *malloc(size_t size); | This function allocates an array of num bytes and leave them uninitialized. |
void *realloc(void *address, int newsize); | This function re-allocates memory extending it up to newsize. |
Allocating Memory Dynamically
If you are aware of the size of an array, then it is easy and you can define it as an array. For example, if you need to store the name of a person, then you can safely define an array to hold a maximum of 100 characters (assuming that a name wouldn't contain more than 100 characters). So, you can define an array as follows −
char name[100];
This is an example of static memory allocation. Now let us consider a situation where you have no idea about the length of the text you need to store, for example, you want to store a detailed description about a topic. In such a case, if the content is less than the allocated size, the allocated memory is wasted during the program’s execution.
On the other hand, if the size required is more than the allocated memory size, it may lead to unpredictable behaviour, including causing the data to be corrupted, as the size of the array cannot be dynamically altered.
It is in these kind of situations you need to use the dynamic memory allocation methods as described in this chapter.
The malloc() Function
This function is defined in the stdlib.h header file. It allocates a block memory of the required size and returns a void pointer.
void *malloc (size)
The size parameter refers to the block of memory in bytes. To allocate a memory required for a specified data type, you need to use the typecasting operator.
For example, the following snippet allocates the memory required to store an int type −
int *ptr; ptr = (int *) malloc (sizeof (int));
Here we need to define a pointer to character without defining how much memory is required and later, based on requirement, we can allocate memory.
Example
The following example uses the malloc() function to allocate the required memory to store a string (instead of declaring a char array of a fixed size) −
#include <stdio.h> #include <stdlib.h> #include <string.h> int main() { char *name; name = (char *) malloc(strlen("TutorialsPoint")); strcpy(name, "TutorialsPoint"); if(name == NULL) { fprintf(stderr, "Error - unable to allocate required memory\n"); } else { printf("Name = %s\n", name); } }
Output
When the above code is compiled and executed, it produces the following output −
Name = TutorialsPoint
The calloc() Function
The calloc() function (stands for contiguous allocation) allocates the requested memory and returns a pointer to it.
void *calloc(n, size);
Here, "n" is the number of elements to be allocated and "size" is the byte-size of each element.
The following snippet allocates the memory required to store 10 int types −
int *ptr; ptr = (int *) calloc(25, sizeof(int));
Example
Let's rewrite the above program using the calloc() function. All that you need to do is replace malloc with calloc −
#include <stdio.h> #include <stdlib.h> #include <string.h> int main() { char *name; name = (char *) calloc(strlen("TutorialsPoint"), sizeof(char)); strcpy(name, "TutorialsPoint"); if(name == NULL) { fprintf(stderr, "Error - unable to allocate required memory\n"); } else { printf("Name = %s\n", name); } }
So you have complete control and you can pass any size value while allocating memory, unlike arrays where once the size is defined, you cannot change it.
Resizing and Releasing the Memory
When your program comes out, the operating system automatically releases all the memory allocated by your program. However, it is a good practice to release the allocated memory explicitly by calling the free() function, when you are not in need of using the allocated memory anymore.
In this section, we will highlight the use of two functions, realloc() and free(), that you can use to resize and release the allocated memory.
The realloc() Function
The realloc() (re-allocation) function in C is used to dynamically change the memory allocation of a previously allocated memory. You can increase or decrease the size of an allocated memory block by calling the realloc() function.
The prototype of using the realloc() function is like this −
void *realloc(*ptr, size);
Here, the first parameter "ptr" is the pointer to a memory block previously allocated with malloc, calloc or realloc to be reallocated. If this is NULL, a new block is allocated and a pointer to it is returned by the function.
The second parameter "size" is the new size for the memory block, in bytes. If it is "0" and ptr points to an existing block of memory, the memory block pointed by ptr is deallocated and a NULL pointer is returned.
Example
The following example demonstrates how you can use the realloc() function in a C program −
#include <stdio.h> #include <stdlib.h> #include <string.h> int main() { char *name; name = (char *) calloc(strlen("TutorialsPoint"), sizeof(char)); strcpy(name, "TutorialsPoint"); name = (char *) realloc(name, strlen(" India Private Limited")); strcat(name, " India Private Limited"); if(name == NULL) { fprintf(stderr, "Error - unable to allocate required memory\n"); } else { printf("Name = %s\n", name); } }
Output
When the above code is compiled and executed, it produces the following output −
Name = TutorialsPoint India Private Limited
The free() Function
The free() function in C is used to dynamically de-allocate the memory allocated using functions such as malloc() and calloc(), since it is not freed on their own.
In C programming, any reference to unused memory creates a garbage deposition, which may lead to problems like program crashing. Hence, it is wise to use the free() function to perform a manual cleaning operation of the allocated memory.
Here is the prototype to use the free() function −
void free(void *ptr);
Where ptr is the pointer to the block of memory previously allocated.
Example
The following example demonstrates how you can use the free() function in a C program −
#include <stdio.h> #include <stdlib.h> #include <string.h> int main() { char *name; name = (char *) calloc(strlen("TutorialsPoint"), sizeof(char)); strcpy(name, "TutorialsPoint"); if(name == NULL) { fprintf(stderr, "Error - unable to allocate required memory\n"); } else { printf("Name = %s\n", name); free(name); } }
Output
At the end of the code, the memory allocated to the char * pointer is de-allocated.
Name = TutorialsPoint India Private Limited