How to Allocate Struct Memory With malloc in C
-
Use
malloc
With thesizeof
Operator to Allocate Struct Memory in C -
Use the
for
Loop to Allocate Memory for an Array of Structs in C -
Allocate Memory Using
calloc
for Initializing to Zero in C - Conclusion
Allocating memory for structures is a fundamental aspect of C programming, especially when dealing with dynamic data structures or objects that vary in size during program execution. The use of malloc
in C allows for efficient and flexible memory allocation, particularly when dealing with custom-defined structures.
The article covers essential aspects, such as the syntax of malloc
and how it operates in conjunction with the sizeof
operator to allocate memory specifically tailored to the size of a structure. Additionally, it explores scenarios involving single and array-based struct allocations, along with allocating memory using calloc
for initializing to zero in C.
Use malloc
With the sizeof
Operator to Allocate Struct Memory in C
malloc
is the core function for dynamic memory allocation in C that takes a single integer argument representing the number of bytes to be allocated. To allocate the memory of the custom struct
object that has been defined, we should call the sizeof
operator and retrieve the amount of memory the object needs to be stored.
Syntax of malloc
:
void* malloc(size_t size);
Parameters:
size
: Specifies the number of bytes to allocate in memory.
Return Type:
void*
: It returns a void pointer (void*
) that can be implicitly cast to any other pointer type. This pointer points to the allocated memory block.
Syntax of sizeof
:
sizeof(type);
Parameters:
type
: Represents the variable, data type, or expression for which the size needs to be determined.
Return Type:
- The
sizeof
operator returns a value of typesize_t
, which is an unsigned integral type.
Note that we can pass the sizeof(MyObject)
expression directly into the malloc
call as an argument. One caveat about malloc
is that successfully allocated memory is not initialized, meaning that there may be some garbage values stored.
To counter this issue, the C library provides another useful function - calloc
to automatically initialize the memory region with zero. The following example shows memory allocation for the single MyObject
structure.
#include <stdio.h>
#include <stdlib.h>
enum VALID { FALSE, TRUE };
typedef struct {
int valid;
int *data;
size_t size;
} MyObject;
int main() {
int *tmp = NULL;
MyObject *my1 = malloc(sizeof(MyObject));
my1->valid = TRUE;
my1->data = tmp;
my1->size = sizeof tmp;
free(my1);
exit(EXIT_SUCCESS);
}
However, note that my1->size = sizeof tmp;
assigns the size of the pointer tmp
(usually 4 or 8 bytes, depending on the system architecture), not the size of the memory block tmp
points to. To obtain the size of the data pointed to by tmp
, sizeof(*tmp)
should be used instead.
Below is another example that involves using malloc
to allocate memory for a single instance of a structure.
#include <stdio.h>
#include <stdlib.h>
// Define a sample struct
struct SampleStruct {
int id;
char name[20];
};
int main() {
// Allocate memory for a single struct instance
struct SampleStruct *singleStruct =
(struct SampleStruct *)malloc(sizeof(struct SampleStruct));
if (singleStruct == NULL) {
printf("Memory allocation failed!\n");
return -1;
}
// Access and modify struct members
singleStruct->id = 1;
snprintf(singleStruct->name, sizeof(singleStruct->name), "John Doe");
// Use the allocated memory
// Free allocated memory
free(singleStruct);
return 0;
}
This code demonstrates the allocation, usage, and deallocation of memory for a single instance of the SampleStruct
structure. It’s a basic example showcasing how to dynamically allocate memory for a struct, access its members, perform operations, and release the allocated memory to prevent memory leaks.
Use the for
Loop to Allocate Memory for an Array of Structs in C
It’s often useful to declare an array of structures, which may require a larger memory region than available on the stack. Thus, we need to allocate the array as dynamic memory.
In this method, memory is allocated to store an array of structures using malloc
.
The following example code demonstrates the case when the array of 100 pointers to the MyObject
structs is declared on the stack, but each individual MyObject
object is allocated on dynamic memory (heap).
Note that we also implemented the initMyObject
function to initialize each member in the MyObject
for testing purposes only. The function returns -1
if the passed pointer is null
, and the if
statement is put in the for
loop to make sure the corresponding error message is printed.
#include <stdio.h>
#include <stdlib.h>
#define MAX 100
enum VALID { FALSE, TRUE };
typedef struct {
int valid;
int *data;
size_t size;
} MyObject;
int initMyObject(MyObject *obj, int val, int *dat, size_t siz) {
if (!obj) return -1;
obj->valid = val;
obj->data = dat;
obj->size = siz;
return 0;
}
int main() {
int *tmp = NULL;
MyObject *arr[MAX];
for (int i = 0; i < MAX; ++i) {
arr[i] = malloc(sizeof(MyObject));
if (initMyObject(arr[i], TRUE, tmp, sizeof(tmp)) == -1) {
fprintf(stderr, "[ERROR] initMyObject() failed\n");
break;
}
}
printf("finished\n");
exit(EXIT_SUCCESS);
}
However, there’s an erroneous part of the previous program that can not be allowed in any production code. The program exits without deallocating memory regions that have been dynamically allocated in the loop.
Note that, similar to the allocation, each element of the array must be freed. Thus, we implemented a separate function, deallocMyObjectArray
, to execute iterative calls to free
in the following code sample.
#include <stdio.h>
#include <stdlib.h>
#define MAX 100
enum VALID { FALSE, TRUE };
typedef struct {
int valid;
int *data;
size_t size;
} MyObject;
int initMyObject(MyObject *obj, int val, int *dat, size_t siz) {
if (!obj) return -1;
obj->valid = val;
obj->data = dat;
obj->size = siz;
return 0;
}
int deallocMyObjectArray(MyObject *arr[], size_t len) {
if (!arr) return -1;
for (int i = 0; i < len; ++i) free(arr[i]);
return 0;
}
int main() {
int *tmp = NULL;
MyObject *arr[MAX];
for (int i = 0; i < MAX; ++i) {
arr[i] = malloc(sizeof(MyObject));
if (initMyObject(arr[i], TRUE, tmp, sizeof(tmp)) == -1) {
fprintf(stderr, "[ERROR] initMyObject() failed\n");
break;
}
}
deallocMyObjectArray(arr, MAX);
printf("finished\n");
exit(EXIT_SUCCESS);
}
This code defines a structure MyObject
containing valid
, data
, and size
members. It includes functions to initialize and deallocate an array of MyObject
instances.
In main
, it dynamically allocates memory for an array of MyObject
objects, initializes them, and then deallocates the memory to prevent memory leaks.
The program demonstrates controlled memory management for an array of structures using dynamic memory allocation and deallocation functions.
Allocate Memory Using calloc
for Initializing to Zero in C
calloc
is a function in the C programming language used for dynamically allocating memory from the heap during runtime. It stands for contiguous allocation
, and it allocates a block of memory for an array of elements, initializing the memory block to zero.
The syntax for calloc
is:
void* calloc(size_t numElements, size_t sizeOfType);
numElements
: Number of elements to allocate.sizeOfType
: Size of each element in bytes.
calloc
allocates memory for a specified number of elements of a structure and initializes all bytes to zero.
Example Code:
#include <stdio.h>
#include <stdlib.h>
// Define a sample struct
struct SampleStruct {
int id;
char name[20];
};
int main() {
int numStructs = 3; // Number of structs to allocate
// Allocate memory and initialize to zero for an array of structs
struct SampleStruct *zeroInitialized =
(struct SampleStruct *)calloc(numStructs, sizeof(struct SampleStruct));
if (zeroInitialized == NULL) {
printf("Memory allocation failed!\n");
return -1;
}
// Access and modify struct members
zeroInitialized[0].id = 1;
snprintf(zeroInitialized[0].name, sizeof(zeroInitialized[0].name), "Alice");
// Use the allocated memory
// Free allocated memory
free(zeroInitialized);
return 0;
}
This code demonstrates the usage of calloc
to allocate memory for an array of SampleStruct
structures and initialize them to zero. It showcases how to access and modify members of the allocated structures and appropriately deallocate the allocated memory.
Overall, it illustrates the controlled and zero-initialized memory allocation for a structured data array in C programming.
Conclusion
The article delves into memory allocation for structs in C, emphasizing the use of malloc
, sizeof
, and related techniques. It explores the syntax and function of malloc
alongside the sizeof
operator, showcasing their synergy in accurately allocating memory for custom structures.
By presenting code examples, the article illustrates the allocation, utilization, and deallocation of memory for single structs and arrays of structs. It addresses the initialization caveat of malloc
, advocating for calloc
as a solution that not only allocates memory but also initializes it to zero.
Overall, the article offers a comprehensive guide to effectively manage struct memory in C, emphasizing best practices for dynamic memory allocation and proper memory deallocation to ensure efficient and robust programs.
Founder of DelftStack.com. Jinku has worked in the robotics and automotive industries for over 8 years. He sharpened his coding skills when he needed to do the automatic testing, data collection from remote servers and report creation from the endurance test. He is from an electrical/electronics engineering background but has expanded his interest to embedded electronics, embedded programming and front-/back-end programming.
LinkedIn Facebook