Another popular way to provide initializers and deinitializers for your structure is to only operate on already allocated memory. This approach is more general as it allows your structure to be used both, stack and heap allocated.
struct dynamic_array
{
double * data;
size_t size;
};
int
dynamic_array_init(struct dynamic_array *const dyn_arr_ptr,
const size_t size)
{
if (dyn_arr_ptr == NULL)
return -1; /* invalid argument */
/* Allocate an array initially filled with zeros. */
dyn_arr_ptr->data = calloc(size, sizeof(double));
if (dyn_arr_ptr->data == NULL)
return -1; /* out of memory */
dyn_arr_ptr->size = size;
return 0; /* success */
}
int
dynamic_array_deinit(struct dynamic_array *const dyn_arr_ptr)
{
if (dyn_arr_ptr == NULL)
return 0; /* nothing to do */
free(dyn_arr_ptr->data);
dyn_arr_ptr->data = NULL;
dyn_arr_ptr->size = 0;
return 0;
}
It can then be used to initialize a stack-based structure…
struct dynamic_array dyn_arr;
if (dynamic_array_init(&dyn_arr, 42) < 0)
{
fprintf(stderr, "error: cannot initialize array\n");
return EXIT_FAILURE;
}
/* Use the dynamic array... */
dynamic_array_deinit(&dyn_arr);
… as well as a heap-based one.
struct dynamic_array * dyn_arr_ptr = malloc(sizeof(struct dynamic_array));
if (dynamic_array_init(dyn_arr_ptr, 42) < 0)
{
fprintf(stderr, "error: cannot initialize array\n");
return EXIT_FAILURE;
}
/* Use the dynamic array... */
dynamic_array_deinit(dyn_arr_ptr);
free(dyn_arr_ptr);
Note that I can pass the result of malloc
unchecked to the initializer function because it does a NULL
check and handles this case gracefully.