3

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

3 Answers 3

3
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;
}
Sign up to request clarification or add additional context in comments.

2 Comments

If he's using C, he doesn't need to cast the pointer back from malloc explicitly.
If getNumBars() is untrusted user input, you should test that the multiplication by sizeof *myFoo doesn't wrap around.
1

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);

Comments

0

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));
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.