简体   繁体   中英

How to declare and initialize this array of structs in C when the length is not known till runtime?

foo.c

#include "main.h"
unsigned char currentBar;
struct foo myFoo[getNumBars()];

void initMyFoo(void)
{
 currentBar=(getNumBars()-1);
 for(i=0; i<(sizeof(myFoo)/sizeof(myFoo[0])); i++)
 {
  myFoo[i].we = 1;
  myFoo[i].want = 0;
  myFoo[i].your = 0;
  myFoo[i].soul = 0;
 }
}

main.c

#include "foo.h"
unsigned char getNumBars()
{
 return getDipSwitchValues();
}
initMyFoo();

(struct foo is declared in foo.h.)

This code has to execute without hard coding a number for Bars, as the number of Bars will change according to whatever the user sets his DIP switches. Right now I'm not able to initialize myFoo; I get the error "constant expression expected in initializer." Do I have to initialize it like:

struct foo myFoo[];

and change it later? If so, how do I make myFoo[] the correct length? I obviously don't have a constant available that corresponds to the desired size. Do I need to dynamically allocate this or something?

I found this similar answer but it wasn't too helpful for me - C++ a class with an array of structs, without knowing how large an array I need

struct foo* myFoo;
unsigned int myFooSize;

void initMyFoo(void)
{
  myFooSize = getNumBars();
  myFoo = malloc(myFooSize * sizeof(*myFoo));
  for (i=0; i<myFooSize; i++) {
    /* ... */
  }
}

void cleanupMyFoo(void)
{
  free(myFoo);
  myFoo = NULL;
  myFooSize = 0;
}

1 - in C99 you can use variable length arrays , which allow you to create arrays whose lengths are runtime-determined. You can also use them via compiler extensions (GCC supports them for non-C99 C and C++), but that's not a portable solution.

int someUnknownSize = 0;

/* some code that changes someUnknownSize */

struct foo myFoo[someUnknownSize];

2 - Declare a pointer that will be allocated memory at runtime with malloc or calloc .

struct foo *fooPtr = 0; /* null pointer to struct foo */
int sizeToAlloc = 0;
/* determine how much to allocate/modify sizeToAlloc */
fooPtr = malloc(sizeToAlloc * sizeof(*fooPtr));

/* do stuff with the pointer - you can treat it like you would an array using [] notation */
free(fooPtr);

I usually go for an expected maximum array size and if it's needed, just resize it:

type * a = calloc(sizeof(type),exp_array_size);

and upon pushing a new value onto the array (yeak, OK, I treat it as if it was a stack...), I check its current size against the new one:

if (current_size > max_size) {
    max_size *= 2;
    realloc(a,max_size*sizeof(type));
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM