How to Allocate Struct Memory With malloc in C

Jinku Hu Feb 12, 2024
  1. Use malloc With the sizeof Operator to Allocate Struct Memory in C
  2. Use the for Loop to Allocate Memory for an Array of Structs in C
  3. Allocate Memory Using calloc for Initializing to Zero in C
  4. Conclusion
How to Allocate Struct Memory With malloc in C

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 type size_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.

Author: Jinku Hu
Jinku Hu avatar Jinku Hu avatar

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

Related Article - C Struct