0
typedef struct
{
    int blah;
    int bleh;
} Foo;

typedef struct
{
    int a;
    int b;
    Foo* arr[];
} Bar;

int main(int argc, char **argv)
{
    Bar* bar = malloc(sizeof(Bar) + sizeof(Foo) * 5);
    Foo foo1 = bar->arr[0];
    return 0;
}

On the line where foo1 is assigned, I get "invalid initializer". If I change the type to Foo*, it compiles. But then if I do foo1->blah = 3, the program crashes.

Why is the type of array elements Foo* and not Foo? And why is the program crashing?

ryeguy
  • 65,519
  • 58
  • 198
  • 260
  • 1
    'Why is the type of array elements Foo*' -- because, of course, you declared them to be with `Foo* arr[]` – Jim Balter May 29 '13 at 02:39

3 Answers3

3

arr is an array of Foo* so you can not assign an element of arr to a Foo here:

 Foo foo1 = bar->arr[0];

the second issue is even if you were allocating memory for arr properly you need to initialize each pointer as well, otherwise you are dereferencing an uninitialized pointer which is undefined behavior.

If you want an array of Foo then this is what you want:

typedef struct
{
    int a;
    int b;
    Foo arr[];
} Bar;

then the rest of your code does not change.

This is using flexible array members introduced in C99 and the answers here talk about how to allocate and free properly.

Community
  • 1
  • 1
Shafik Yaghmour
  • 154,301
  • 39
  • 440
  • 740
2

The type of array elements is Foo * because this is exactly how you declared them. The declaration Foo* arr[] stands for an array of Foo * elements. Why did you expect the elements to be Foo, when you explicitly said Foo * in the declaration?

Changing the type of foo1 to Foo * looks like a random change that does not make much sense. What are you trying to do - this is the question you should answer first. What kind of array do you need at the end of Bar? Foo arr[] or Foo *arr[]?

Judging by your malloc it appears that you want to declare an array of Foo elements at the end of Bar. If so, you have to change the array declaration to Foo arr[].

AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
1

Foo* arr[] is an array of pointers, so bar->arr[0] is a pointer.

This works fine:

Foo* foo1 = bar->arr[0];

To create an object of Foo you can use either one of the following

Foo bar1 = *bar->arr[0] // or **bar->arr; though this may be less clear 
Nobilis
  • 7,310
  • 1
  • 33
  • 67