具有支架初始化的柔性阵列构件的尺寸

时间:2016-02-22 10:26:43

标签: c

假设我有这段代码:

const struct
{
  const char * const name;
  const unsigned length;
  const char data[951357];
} var[] =
{
  {
    "dataset1",
    #include "dataset1.h"
  },
  {
    "dataset2",
    #include "dataset2.h"
  },
  /* ... */
};

每个dataset*.h都包含以下内容:

6,
{
  0x04, 0x08, 0x15, 0x16, 0x23, 0x42
}

这要求我事先知道最大数据集的大小。这不是面向未来的,因为任何添加数据集的人都必须检查并修改data的大小,并且可能导致严重的内存浪费(在我的实际情况中,已经有~15个数据集,大小不等,数百KB)

有什么方法吗?

唯一的硬性要求是每个数据必须位于自己的文件中,但该文件的格式可以是任何格式。我还希望将所有内容保留为const

编辑:我应该提一下旧代码是这样做的:

struct dataset { char* name; int length; char* data; };
struct dataset *alldata[10];
struct dataset dataset1 = {
  "dataset1",
  #include "dataset1.h"
};
/* same again for every dataset */
int main()
{
  alldata[0] = malloc(sizeof(struct dataset));
  memcpy(alldata[0], dataset1, sizeof(struct dataset));
  /* again, block copied for each dataset */
}

这段代码对我来说很难看,并且需要(我认为)不必要的mem副本。我重写代码的目的是让它在编译时存储所有数据,然后在运行时只在必要时读取它。

2 个答案:

答案 0 :(得分:1)

您可以使用指向数据的指针。你为额外的指针付出代价,但考虑到数据的大小,你可以节省很多,因为没有太大的数组。

#include "dataset1.h"
/* other dataset includes here */
struct DataSet {
    const char * name;
    unsigned length;
    const char * data;
};
const struct DataSet var[] = {
     {
         "dataset1",
        dataset1_length,
        dataset1_data,
     },
     /* other dataset inits here */
};

<强> dataset1.h

enum { dataset1_length = 6 };
extern const char dataset1_data[];

<强> dataset1.c

const char dataset1_data[] = { 0x04, 0x08, 0x15, 0x16, 0x23, 0x42 };

请注意我删除了不必要的const,但所有数据仍为const

如果不需要额外的编译单元,只需将​​标题和源文件合并到一个标题中并直接包含:

<强> dataset1.h

enum { dataset1_length = 6 };
const char dataset1_data[] = { 0x04, 0x08, 0x15, 0x16, 0x23, 0x42 };

答案 1 :(得分:1)

您想要创建一个结构数组。数组要求每个元素的大小相同。说由于灵活的数组,你不能使用不同大小的结构创建任何数组,除非你修改数组成员的大小(正如你所做的那样)。 无论如何都有一个解决方案。使用指针更改可变长度数组成员,并在其他位置创建可变长度数组 我将解释的解决方案让您继续使用数组访问方法,因此您无需更改其余软件,只需对头文件进行少量修改。
主要结构声明将是:

const struct
{
  const char const * name;
  const unsigned length;
  const char const *data;    //This is the only difference
} var[] =
{
  {
    "dataset1",
    #include "dataset1.h"
  },
  {
    "dataset2",
    #include "dataset2.h"
  },
  /* ... */
};

标题文件将按照以下方式制作:

6,
(const char const *)&(const char[]) {0x04, 0x08, 0x15, 0x16, 0x23, 0x42}

这里,(const char[]){0x04, 0x08, 0x15, 0x16, 0x23, 0x42}部分在内存中创建了一个可变长度的char常量数组。然后使用运算符&获取其地址并将其转换为char指针,然后再将其分配给结构 在C99-C11下测试