【问题标题】:non-static initialization of a flexible array member灵活数组成员的非静态初始化
【发布时间】:2017-06-08 21:20:43
【问题描述】:

我正在尝试使用在运行时创建的数组填充结构成员并收到以下错误:

error: non-static initialization of a flexible array member
             .entries = entries
                        ^

我已经隔离了问题并用更简单的代码重现了它,以使其更清晰:

#include <stdlib.h>

typedef struct entry {
    char *title;
    int id;
} Entry;

typedef struct collection {
    size_t size;
    Entry entries[];
} Collection;

// This function signature may not be changed
void populate(int n, Collection *result){

    Entry entries[n];

    for (int i = 0; i < n; ++i) {
        Entry entry = {
                .title = "Title",
                .id = i
        };

        entries[i] = entry;
    }

    Collection collection = {
            .size = n,
            .entries = entries
    };

    result = &collection;
}

我该如何解决这个问题?

【问题讨论】:

  • 您必须使用malloc() 为每个Entry 分别分配内存。您必须假设调用者已经在Collection *result 中分配了足够的内存。
  • this一样使用memcpy
  • 您必须为标题显式分配内存。就像 BLUEPIXY 说的那样使用 malloc
  • 如前所述,collection 是一个局部变量,当您将其地址分配给*result 时,它的生命周期即将结束。因此,该函数会将一个悬空指针存储到其 out 参数中,与初始化 collection 的问题无关。
  • 作为函数参数传递的变量不能被该函数更改。

标签: c arrays memory-management struct


【解决方案1】:

实际上,使用灵活的数组成员初始化结构并不简单;您必须为稍后要复制的条目分配一个具有足够空间的集合项目。因此,您可以编写如下内容:

Collection *coll = malloc(sizeof(Collection)+n*sizeof(Entry));
coll->size = n;
memcpy (coll->entries, entries, n*sizeof(Entry));

我认为除了使用这种“手写”malloc之外别无他法。

但是请注意,如果希望在函数 populate 中完成内存分配,函数 populate 的签名不能保持原样,因为它不允许“返回”或设置指向新分配的指针Collection-对象。在这种情况下,必须将签名更改为 void populate(int n, Collection **result)Collection *populate(int n)

【讨论】:

  • 还要注意函数必须返回一个指向分配结构的指针。由于 malloc 必须在函数内部使用,void populate(int n, Collection *result) 的格式不好。最好改成Collection* populate(int n)
  • @Lundin:对;我认为程序的设计必须重新设计,以便以有意义的方式处理灵活的数组成员。
猜你喜欢
  • 1970-01-01
  • 2015-03-07
  • 2011-08-04
  • 1970-01-01
  • 1970-01-01
  • 2013-04-13
  • 2018-08-03
  • 2011-12-02
  • 1970-01-01
相关资源
最近更新 更多