In C programming, dynamic memory allocation is an important concept as it allows a program to allocate memory dynamically at run time instead of having to pre-allocate memory during compile time. The C library provides two important functions, malloc() and free(), that we can use to dynamically allocate and free memory. In this tutorial, we will learn how to use malloc in C and its associated functions, as well as explore some real-life examples.
Prerequisites
A basic but well-rounded understanding of C programming. You can acquire these by checking out the following posts:
- Functions in C Programming With Examples: Simplified
- How to Master Data Types in C: A Beginner’s Guide
- How to Get Started with C Programming for Beginners
- Implementation of the strcpy() function in C
What is Malloc in C?
Malloc() is a function in the C programming language that is used to dynamically allocate memory during program execution. It is part of the <stdlib.h> library.
Malloc stands for “memory allocation” and is used to reserve a block of memory of a specified size. The memory block that is allocated by the malloc function can be used to store data during the program’s execution.
When you allocate memory using malloc(), the memory remains allocated until it is explicitly freed using the free() function.
Syntax of Malloc in C
The syntax of malloc() is as follows:
void *malloc(size_t size);
Here, size is the number of bytes to allocate.
The return value is a pointer to the first byte of the allocated memory block.
The void pointer is used because malloc() can allocate memory for any data type.
How to use malloc in c
The basic steps to use malloc() in C are as follows:
- Declare a pointer variable of the desired data type.
- Allocate memory using malloc()
- Use the allocated memory.
- Free the memory using free() when you are done.
Let’s take a look at an example.
Suppose we want to create an array of integers with a length that is determined at runtime. We can do this using malloc().
#include <stdio.h>
#include <stdlib.h>
int main() {
int n;
printf("Enter the number of elements: ");
scanf("%d", &n);
int *arr = malloc(n * sizeof(int));
if (arr == NULL) {
printf("Memory allocation failed.");
exit(1);
}
printf("Enter the elements: ");
for (int i = 0; i < n; i++) {
scanf("%d", &arr[i]);
}
printf("The elements of the array are: ");
for (int i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
free(arr);
return 0;
}
In this code, we first prompt the user to enter the number of elements they want to enter for the array using printf()
. Then we use scanf()
to read this input and store it in the variable n
.
We then dynamically allocate memory for the array arr
using a single call to malloc()
with the size calculated as n * sizeof(int)
.
We validate whether the allocation was successful or not by checking if the pointer arr
is NULL
.
Next, we prompt the user to enter the elements of the array using printf()
. We then use a loop to read n
number of integer inputs from the user using scanf()
, and store them in the array arr
.
Finally, we print the elements of the array using printf()
and free the allocated memory using free()
.
This code achieves the same functionality as the previous code example but uses only one call to scanf()
.
Tasks
Write a function that creates an array of chars, and initializes it with a specific char.
- Prototype: char *create_array(unsigned int size, char c);
- Returns NULL if size = 0
- Returns a pointer to the array, or NULL if it fails
Solution
#include <stdio.h>
#include <stdlib.h>
char *create_array(unsigned int size, char c) {
if (size == 0) {
return NULL;
}
char *arr;
arr = malloc(size * sizeof(char));
if (arr == NULL) {
return NULL;
}
for (unsigned int i = 0; i < size; i++) {
arr[i] = c;
}
return arr;
}
In this implementation, the function takes two parameters: size
, which is the size of the array to be created, and c
, which is the character to initialize the array with.
The function first checks if the size is 0. If it is, it returns NULL
.
Next, it allocates memory for the array using malloc()
. If the allocation fails, it also returns NULL
.
Finally, it initializes each element of the array with the character c
, and returns a pointer to the array.
Here’s an example usage of the create_array()
function:
#include <stdio.h>
int main() {
char *arr = create_array(10, 'a');
if (arr == NULL) {
printf("Memory allocation failed.");
exit(1);
}
for (unsigned int i = 0; i < 10; i++) {
printf("%c ", arr[i]);
}
free(arr);
return 0;
}
In this example, we create an array of size 10 and initialize it with the character ‘a’ using the create_array()
function. We then print each element of the array to verify that it has been initialized correctly.
Finally, we free the memory allocated for the array using free()
.
Write a function that returns a pointer to a newly allocated space in memory, which contains a copy of the string given as a parameter.
- Prototype: char *_strdup(char *str);
- The _strdup() function returns a pointer to a new string which is a duplicate of the string str. Memory for the new string is obtained with malloc() and can be freed with free().
- Returns NULL if str = NULL
- On success, the _strdup function returns a pointer to the duplicated string. It returns NULL if insufficient memory was available
Solution:
#include <stdio.h>
#include <stdlib.h>
// Custom implementation of strdup
char* my_strdup(char *str) {
// Check if the input string is NULL
if (str == NULL) {
return NULL;
}
// Get the length of the input string
int len = 0;
while (str[len] != '#include <stdio.h>
#include <stdlib.h>
// Custom implementation of strdup
char* my_strdup(char *str) {
// Check if the input string is NULL
if (str == NULL) {
return NULL;
}
// Get the length of the input string
int len = 0;
while (str[len] != '\0') {
len++;
}
// Allocate memory for the new string
char *new_str = (char*) malloc((len + 1) * sizeof(char));
// Copy the input string to the new string
int i;
for (i = 0; i < len; i++) {
new_str[i] = str[i];
}
new_str[len] = '\0';
return new_str;
}
int main() {
char str1[] = "Hello, world!";
char *str2;
str2 = my_strdup(str1);
printf("Original string: %s\n", str1);
printf("Duplicated string: %s\n", str2);
free(str2);
return 0;
}
') {
len++;
}
// Allocate memory for the new string
char *new_str = (char*) malloc((len + 1) * sizeof(char));
// Copy the input string to the new string
int i;
for (i = 0; i < len; i++) {
new_str[i] = str[i];
}
new_str[len] = '#include <stdio.h>
#include <stdlib.h>
// Custom implementation of strdup
char* my_strdup(char *str) {
// Check if the input string is NULL
if (str == NULL) {
return NULL;
}
// Get the length of the input string
int len = 0;
while (str[len] != '\0') {
len++;
}
// Allocate memory for the new string
char *new_str = (char*) malloc((len + 1) * sizeof(char));
// Copy the input string to the new string
int i;
for (i = 0; i < len; i++) {
new_str[i] = str[i];
}
new_str[len] = '\0';
return new_str;
}
int main() {
char str1[] = "Hello, world!";
char *str2;
str2 = my_strdup(str1);
printf("Original string: %s\n", str1);
printf("Duplicated string: %s\n", str2);
free(str2);
return 0;
}
';
return new_str;
}
int main() {
char str1[] = "Hello, world!";
char *str2;
str2 = my_strdup(str1);
printf("Original string: %s\n", str1);
printf("Duplicated string: %s\n", str2);
free(str2);
return 0;
}
In this implementation, the _strdup()
function takes a pointer to a character array str
as a parameter. The function first checks if the input string is NULL
, in which case it returns NULL
.
It then determines the length of the input string using a while loop that counts the number of non-null characters in the string.
The function then allocates memory for the new string using the malloc()
function, with enough space to hold the length of the input string plus one extra character for the null terminator.
The function then copies each character of the input string to the new string using a for loop and adds a null terminator to the end of the new string. Finally, the function returns a pointer to the new string.
In the main()
function, we demonstrate the use of this custom string function by passing a character array str1
to the _strdup()
function to duplicate it, and assign the result to another character pointer str2
.
We then print the original and duplicated strings to the console and free the memory allocated for the duplicated string using the free()
function.
Output:
Original string: Hello, world!
Duplicated string: Hello, world!
Write a function that concatenates two strings.
- Prototype: char *str_concat(char *s1, char *s2);
- The returned pointer should point to a newly allocated space in memory which contains the contents of s1, followed by the contents of s2, and null-terminated
- if NULL is passed, treat it as an empty string
- The function should return NULL on failure
Solution
#include <stdio.h>
#include <stdlib.h>
char *str_concat(char *s1, char *s2) {
if (s1 == NULL) {
s1 = "";
}
if (s2 == NULL) {
s2 = "";
}
int len1 = 0;
while (s1[len1] != '#include <stdio.h>
#include <stdlib.h>
char *str_concat(char *s1, char *s2) {
if (s1 == NULL) {
s1 = "";
}
if (s2 == NULL) {
s2 = "";
}
int len1 = 0;
while (s1[len1] != '\0') {
len1++;
}
int len2 = 0;
while (s2[len2] != '\0') {
len2++;
}
char *new_string;
new_string = malloc((len1 + len2 + 2) * sizeof(char));
if (new_string == NULL) {
printf("Could not allocate memory");
exit(1);
}
int i;
for (i = 0; i < len1; i++) {
new_string[i] = s1[i];
}
new_string[i++] = ' ';
int j;
for (j = 0; j < len2; j++) {
new_string[i + j] = s2[j];
}
new_string[len1 + len2 + 1] = '\0';
return new_string;
}
int main() {
char str1[] = "Hello";
char str2[] = "world!";
char *concat_str;
concat_str = str_concat(str1, str2);
printf("Concatenated string: %s\n", concat_str);
free(concat_str);
return 0;
}
') {
len1++;
}
int len2 = 0;
while (s2[len2] != '#include <stdio.h>
#include <stdlib.h>
char *str_concat(char *s1, char *s2) {
if (s1 == NULL) {
s1 = "";
}
if (s2 == NULL) {
s2 = "";
}
int len1 = 0;
while (s1[len1] != '\0') {
len1++;
}
int len2 = 0;
while (s2[len2] != '\0') {
len2++;
}
char *new_string;
new_string = malloc((len1 + len2 + 2) * sizeof(char));
if (new_string == NULL) {
printf("Could not allocate memory");
exit(1);
}
int i;
for (i = 0; i < len1; i++) {
new_string[i] = s1[i];
}
new_string[i++] = ' ';
int j;
for (j = 0; j < len2; j++) {
new_string[i + j] = s2[j];
}
new_string[len1 + len2 + 1] = '\0';
return new_string;
}
int main() {
char str1[] = "Hello";
char str2[] = "world!";
char *concat_str;
concat_str = str_concat(str1, str2);
printf("Concatenated string: %s\n", concat_str);
free(concat_str);
return 0;
}
') {
len2++;
}
char *new_string;
new_string = malloc((len1 + len2 + 2) * sizeof(char));
if (new_string == NULL) {
printf("Could not allocate memory");
exit(1);
}
int i;
for (i = 0; i < len1; i++) {
new_string[i] = s1[i];
}
new_string[i++] = ' ';
int j;
for (j = 0; j < len2; j++) {
new_string[i + j] = s2[j];
}
new_string[len1 + len2 + 1] = '#include <stdio.h>
#include <stdlib.h>
char *str_concat(char *s1, char *s2) {
if (s1 == NULL) {
s1 = "";
}
if (s2 == NULL) {
s2 = "";
}
int len1 = 0;
while (s1[len1] != '\0') {
len1++;
}
int len2 = 0;
while (s2[len2] != '\0') {
len2++;
}
char *new_string;
new_string = malloc((len1 + len2 + 2) * sizeof(char));
if (new_string == NULL) {
printf("Could not allocate memory");
exit(1);
}
int i;
for (i = 0; i < len1; i++) {
new_string[i] = s1[i];
}
new_string[i++] = ' ';
int j;
for (j = 0; j < len2; j++) {
new_string[i + j] = s2[j];
}
new_string[len1 + len2 + 1] = '\0';
return new_string;
}
int main() {
char str1[] = "Hello";
char str2[] = "world!";
char *concat_str;
concat_str = str_concat(str1, str2);
printf("Concatenated string: %s\n", concat_str);
free(concat_str);
return 0;
}
';
return new_string;
}
int main() {
char str1[] = "Hello";
char str2[] = "world!";
char *concat_str;
concat_str = str_concat(str1, str2);
printf("Concatenated string: %s\n", concat_str);
free(concat_str);
return 0;
}
In this implementation, the str_concat()
function takes two pointers to character arrays s1
and s2
as parameters. The function first checks if either string is NULL
, and if so, it sets the corresponding string to an empty string.
It then determines the lengths of both strings using two separate while loops that count the number of non-null characters in each string. The function then allocates memory for the concatenated string using the malloc()
function, with enough space to hold the lengths of both input strings plus one extra character for the null terminator.
The function then copies each character of the first input string to the concatenated string using a for loop, followed by a second for loop that copies each character of the second input string to the concatenated string. Finally, the function adds a null terminator to the end of the concatenated string.
In the main()
function, we demonstrate the use of this function by passing two character arrays str1
and str2
to the str_concat()
function to concatenate them, and assigning the result to another character pointer concat_str
. We then print the concatenated string to the console, and free the memory allocated for it using the free()
function.
Output
Concatenated string: Hello world!
Conclusion
malloc and free are two important functions in C that allow you to dynamically allocate and deallocate memory at runtime. They are useful when you don’t know the size of the data you need to store beforehand, or when you want to allocate memory only when it is actually needed.
When using malloc, you should always check if the allocation was successful, and when you no longer need the allocated memory, you should deallocate it using free. Failure to deallocate memory can lead to memory leaks, which can cause your program to run out of memory and crash.
Real case examples of using malloc include reading data from a file and dynamically allocating memory for an array based on the number of items in the file, and allocating memory for a string and copying it to another string without using the strlen and strcpy library functions.
Overall, understanding how to use malloc and free is an important skill for any C programmer, and can help you write more efficient and flexible programs.
If you found this information on how to use malloc in C helpful, please consider sharing it with others who may benefit from it. Don’t forget to leave a comment and let us know if you have any questions or suggestions. You can also join our forum and community for further assistance with your C programming needs. Thank you for your support!
For more details, check – Dynamic memory allocation in C – malloc calloc realloc free
Hi roland I quite appreciate your efforts in putting a useful material like this, so simplified and makes fall in love with c and linux.
Please I would like you to help me with the team projects on printf and the simple shell. I need you to do a detailed breakdown of this projects and the code solutions with explanations for me.
Thanks
Thanks for the feedback.
Will try my best for the printf and shell project explanations