Googlebot
Googlebot

Reputation: 15673

Memory allocation of an array of struct in a C function

I am trying to pass the pointer to a struct to a function to create an array of the struct there. The overall idea is:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

typedef struct items
{
  int number;
  char *name;
  char *description;
} ITEMS;

int process(ITEMS **items)
{
  int i = 0, something = 200;
  // for loop is for the representation. 
  // The actual data come from MySQL row loop
  for (int j = 100; j < something; j++)
  {
    // Growing the array of struct
    items = realloc(items, (i + 1) * sizeof(*items));

    // Adding items here
    items[i]->number = j;
    strcpy(items[i]->name, "Some name"); // it comes from a variable
    strcpy(items[i]->description, "Some text");
    i++;
  }

  return i;
}

int main()
{

  ITEMS *items;
  int num_items = process(&items);

  for (int i = 0; i < num_items; i++)
  {
    printf("%d - %s - %s\n", items[i].number, items[i].name,
        items[i].description);
  }
  return 0;
}

but I am struggling with reallocating the memory for the struct (and with the pointers too).

Upvotes: 0

Views: 78

Answers (1)

user3121023
user3121023

Reputation: 8286

The pointer to pointer must be de-referenced in the function so the allocation is visible in the calling function.
strdup is use to allocate memory to the pointers in the structure.
It is better to use a temporary variable for the reallocation.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

typedef struct items
{
  int number;
  char *name;
  char *description;
} ITEMS;

int process(ITEMS **items)
{
  int i = 0;
  // Growing the array of struct
  *items = realloc(*items, (i + 1) * sizeof(**items));
  // repeating this step in a loop of adding items

  // Adding items here
  (*items)[i].number = 72;
  (*items)[i].name = strdup( "Some name"); // it comes from a variable
  (*items)[i].description = strdup ("Some text");
  i++;

  *items = realloc(*items, (i + 1) * sizeof(**items));
  // another item
  (*items)[i].number = 88;
  (*items)[i].name = strdup( "Some name"); // it comes from a variable
  (*items)[i].description = strdup ("Some text");
  i++;

  return i;
}

int main()
{

  ITEMS *items = NULL;
  int num_items = process(&items);

  for (int i = 0; i < num_items; i++)
  {
    printf("%d - %s - %s\n", items[i].number, items[i].name, items[i].description);
  }
  return 0;
}

With better error detection

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

typedef struct items
{
  int number;
  char *name;
  char *description;
} ITEMS;

int process(ITEMS **items)
{
    ITEMS *temp = NULL;
    int i = 0;
    // Growing the array of struct
    if ( NULL == ( temp = realloc(*items, (i + 1) * sizeof(**items)))) {
        fprintf ( stderr, "realloc problem\n");
        return i;
    }
    *items = temp;
    // repeating this step in a loop of adding items

    // Adding items here
    (*items)[i].number = 72;
    (*items)[i].name = strdup( "Some name"); // it comes from a variable
    (*items)[i].description = strdup ("Some text");
    i++;

    if ( NULL == ( temp = realloc(*items, (i + 1) * sizeof(**items)))) {
        fprintf ( stderr, "realloc problem\n");
        return i;
    }
    *items = temp;
    // another item
    (*items)[i].number = 88;
    (*items)[i].name = strdup( "Some name"); // it comes from a variable
    (*items)[i].description = strdup ("Some text");
    i++;

    return i;
}

int main()
{

    ITEMS *items = NULL;
    int num_items = process(&items);

    for (int i = 0; i < num_items; i++)
    {
        printf("%d - %s - %s\n", items[i].number, items[i].name, items[i].description);
    }
    return 0;
}

Upvotes: 4

Related Questions