Dawson
Dawson

Reputation: 573

Mallocing array of structs within a struct (C)

I'm having trouble finding the answer to this problem; I've found similar examples of this online but none that address my problem.

I have a struct for the data for a company, Company, and a second struct for collections of companies, Consortium. The second struct will contain variable length arrays of the first struct, the company data struct. The number of elements of the variable length arrays will depend on the number of companies in a consortium.

I want to dynamically allocate whatever is required but I'm getting a bit lost. These are the structs:

typedef struct {
    char  code[];
    double sharePrice;
    int numShares;
    double totalVal;
    double totalDebts;
} Company;

typedef struct {
    int numCore;
    int numAssoc;
    Company core[];
    Company assoc[];
} Consortium;

There will be a number of core companies, and this number will be the size of the core array in the Consortium struct. Same goes for associate companies.

I came up with this expression but I'm not sure what I'm missing:

Consortium *consort=((Consortium*)malloc((numCore+numAssoc)*(sizeof(Consortium));

Upvotes: 0

Views: 3216

Answers (2)

Richard Chambers
Richard Chambers

Reputation: 17723

You might consider that you make the Consortium struct a bit simpler. Since you have the counts for each type, core and assoc, you can have just a single array, the first part of which is for core and the second part of which is for assoc.

So your struct would look something like the following source (which has not been compiled and is just jotted down rather than tested so caveat emptor):

typedef struct {
    int numCore;    // number of core companies, first part of m_companies
    int numAssoc;   // number of assoc companies, second part of m_companies
    Company m_companies[1];
} Consortium;

Then you would create your actual data structure by something like:

Consortium *makeConsortium (int numCore, int numAssoc) {
  Consortium *pConsortium = malloc (sizeof(Consortium) + sizeof(Company) * (numCore, numAssoc));
  if (pConsortium) {
      pConsortium->numCore = numCore;
      pConsortium->numAssoc = numAssoc;
  }
  return pConsortium;
}

After this you could fill it in by some functions which indicate success or not:

int addCompanyCore (Consortium *pConsortium, int index, Company *pCompany) {
  int iRetStatus = 0;
  if (pConsortium && index < pConsortium->numCore) {
    pConsortium->m_companies[index] = *pCompany;
    iRetStatus = 1;
  }
  return iRetStatus;
}
int addCompanyAssoc (Consortium *pConsortium, int index, Company *pCompany) {
  int iRetStatus = 0;
  if (pConsortium && index < pConsortium->numAssoc) {
    index += pConsortium->numCore;
    pConsortium->m_companies[index] = *pCompany;
    iRetStatus = 1;
  }
  return iRetStatus;
}

And then you would access them with another set of helper functions.

Company  *getCompanyCore (Consortium *pConsortium, int index) {
  Company *pCompany = 0;
  if (pConsortium && index < pConsortium->numCore) {
    pCompany = pConsortium->m_companies + index;
  }
  return pCompany;
}
Company * getCompanyAssoc (Consortium *pConsortium, int index) {
  Company *pCompany = 0;
  if (pConsortium && index < pConsortium->numAssoc) {
    index += pConsortium->numCore;
    pCompany = pConsortium->m_companies + index;
  }
  return pCompany;
}

Upvotes: 0

Jonathan Leffler
Jonathan Leffler

Reputation: 755114

You'll need to use pointers and allocate the arrays separately:

typedef struct
{
    char  *code;
    double sharePrice;
    int numShares;
    double totalVal;
    double totalDebts;
} Company;

typedef struct
{
    int numCore;
    int numAssoc;
    Company *core;
    Company *assoc;
} Consortium;

Consortium *c = malloc(sizeof(*c));    // Error check
c->numCore = 4;
c->core = malloc(sizeof(*c->core) * c->numCore);    // Error check
c->numAssoc = 3;
c->assoc = malloc(sizeof(*c->assoc) * c->numAssoc);    // Error check

for (int i = 0; i < c->numCore; i++)
    c->core[i].code = malloc(32);    // Error check

for (int i = 0; i < c->numAssoc; i++)
    c->assoc[i].code = malloc(32);    // Error check

// Worry about other data member initializations!

It would be simpler and possibly better to modify the Company type to:

typedef struct
{
    char   code[32];
    double sharePrice;
    int    numShares;
    double totalVal;
    double totalDebts;
} Company;

That saves the loops allocating the code elements.

Upvotes: 3

Related Questions