Search code examples
arrayscstructdynamic-arrays

Problem using a dynamic array as a member of a struct


I have two C structs: _Car_, which describes a car, and _Car_List_, which describes a list of cars and contains a dynamic array called cars_. However, when the condition on reallocating memory for cars_ (to avoid an overflow) is triggered the following code stops working:

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

#define SIZE 3

struct _Car_
{
  char* name_;
  int id_;
};

struct _Car_List_
{
  int number_of_cars_;
  int max_number_of_cars_;
  struct _Car_* cars_[];
};


struct _Car_* createCar(int id, char* name)
{
  struct _Car_* car = malloc(sizeof(struct _Car_));

  if (car == NULL)
    return NULL;

  car->name_ = name;
  car->id_ = id;

  return car;
}

int addCar(struct _Car_List_* car_list, int id, char* name)
{
  struct _Car_* car = createCar(id, name);

  if (car_list->number_of_cars_ == car_list->max_number_of_cars_)
  {
    car_list->max_number_of_cars_ = car_list->max_number_of_cars_ + SIZE;
    car_list = realloc(car_list, sizeof(struct _Car_List_) + car_list->max_number_of_cars_ * sizeof(struct _Car_*));

    if (car_list->cars_ == NULL)
      return -1;
  }

  car_list->cars_[car_list->number_of_cars_] = car;
  car_list->number_of_cars_++;

  return 0;
}

void printCars(struct _Car_List_* car_list)
{
  int i = 0;
  struct _Car_* car = car_list->cars_[i];

  while (i < car_list->number_of_cars_)
  {
    printf("- %s [%d]", car->name_, car->id_);

    printf("\n");
    i++;
    car = car_list->cars_[i];
  }
}

int main()
{
  // Here we initialise our list of cars.
  struct _Car_List_* car_list = malloc(sizeof(struct _Car_List_) + SIZE * sizeof(struct _Car_*));
  car_list->number_of_cars_ = 0;
  car_list->max_number_of_cars_ = SIZE;
  printf("Num of cars = %d\n", car_list->number_of_cars_);


  addCar(car_list, 1, "A");
  printf("Num of cars = %d\n", car_list->number_of_cars_);

  addCar(car_list, 2, "B");
  printf("Num of cars = %d\n", car_list->number_of_cars_);

  addCar(car_list, 3, "C");
  printf("Num of cars = %d\n", car_list->number_of_cars_);
  
  addCar(car_list, 4, "D");
  printf("Num of cars = %d\n", car_list->number_of_cars_);

  printCars(car_list);


  return 0;
}

Could you please tell me what I am doing wrong?


Solution

  • You're using reserved names. Don't start a globals and tags with an underscore. And never start anything with _[_A-Z].

    But most importantly, it's unclear what you want to realloc.

    You basically have two choices:

    • have a struct Car_* cars_; in your struct Car_list_, treat that as an array, and realloc that when it's full
    • have a struct Car_ cars_[]; flexible-length array in your struct Car_list_ and realloc the whole thing while accounting for the size needed for the preceding members when the flexible array is full . In this case, your resizing "methods" would need to accept struct Car_list_** rather than just struct Car_list_* because you'll need to be able to communicate the address change of struct Car_list_* to the caller (returning the new struct Car_list_* is also an option)

    Adding another layer of indirection and separately mallocing each struct Car* is probably a waste, but you could do that too and add a * to each of the two above choices accordingly.