为什么gcc说这是一个“无效的初始化器”?

时间:2013-05-29 01:34:38

标签: c

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

在分配了foo1的行上,我收到“无效的初始值设定项”。如果我将类型更改为Foo*,则会进行编译。但是如果我做foo1->blah = 3,程序就会崩溃。

为什么数组元素的类型Foo*而不是Foo?为什么程序会崩溃?

3 个答案:

答案 0 :(得分:3)

arr是一个Foo*的数组,因此您无法在此处arr分配Foo的元素:

 Foo foo1 = bar->arr[0];

第二个问题是,即使您正在为arr正确分配内存,也需要初始化每个pointer,否则您将取消引用未初始化的指针,这是未定义的行为。

如果你想要一个Foo数组,那么这就是你想要的:

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

然后你的其余代码不会改变。

这是使用C99中引入的flexible array members,此处的答案将讨论如何正确分配和释放。

答案 1 :(得分:2)

数组元素的类型是Foo *,因为这正是您声明它们的方式。声明Foo* arr[]代表Foo *元素的数组。当您在声明中明确说出Foo时,为什么期望元素为Foo *

foo1的类型更改为Foo *看起来像是一个没有多大意义的随机更改。你想做什么 - 这是你应该首先回答的问题。在Bar结束时你需要什么样的数组? Foo arr[]Foo *arr[]

根据您的malloc判断,您希望在Foo的末尾声明一个Bar元素数组。如果是这样,您必须将数组声明更改为Foo arr[]

答案 2 :(得分:1)

Foo* arr[]是一个指针数组,因此bar->arr[0]是一个指针。

这很好用:

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

要创建Foo的对象,您可以使用以下任一项

Foo bar1 = *bar->arr[0] // or **bar->arr; though this may be less clear