将灵活数组声明为常量

问题描述 投票:0回答:1

我试图在我的代码中声明一些常量数据结构,理想情况下不必声明子元素(这是关于多个字符串列表的上一个问题的后续内容:不同长度数组)...根据我的上一个问题我可以通过单独声明位来使其工作,但不能一次性声明全部。

我应该添加,我需要一个指向数据结构的指针(指针将位于不同的链接器部分,以便我可以自动发现它们)...

这有效...

struct cpl {
    int x;
    char *a;
    char *b;
    char *list[];
};

const struct cpl one = { 1, "thisa", "thisb", { "one", "two", NULL }};
const struct cpl *xx = &one;

但这会生成有关灵活数组成员的非静态初始化的错误..

const struct cpl *xx = &(const struct cpl){ 2, "thisa", "thisb", { "new", "item", "here", NULL } };

我怀疑答案(假设可能)与之前类似,通过添加某种类型的转换来实现,但我已经尝试了我能想到的一切。

在这种情况下,我可能可以使用第一个版本,但如果我可以避免它,我宁愿不使用它。

任何帮助表示赞赏。

arrays c initialization compound-literals
1个回答
0
投票

灵活数组成员可能主要用于动态内存分配,但没有说它们不能在其他上下文中使用。但是,它们无法初始化,这就是这里的问题。可以通过一些 gcc 扩展来初始化它们。

这又意味着您不能声明具有内部链接的

const
结构并同时使用灵活的数组成员,因为没有标准方法为其赋值。如果我们可以同时拥有它
const
和内部链接,而只能通过
const
限定指针访问它,那么可能会有一些肮脏的解决方法......这个答案中接下来的内容不是真的推荐练习。

如果我们将

struct
替换为
union
并分配足够的内存,然后在该
union
中放入一个匿名结构,那么使用它时 可能 是明确定义的(或者至少是实现定义的行为)。

typedef union {
  struct
  {
    int x;
    char *a;
    char *b;
    char *list[];
  };
  unsigned char lots_of_memory[100];
} cpl;

初始化除灵活数组成员之外的所有内容(如果我们愿意,请务必保持内部链接):

static cpl one = { .x=1, .a="thisa", .b="thisb" };

在运行时初始化灵活数组成员:

memcpy(one.list, (char*[]){ "one", "two", NULL }, sizeof(char*[3]));

只能通过

const
限定指针访问它,作为丢失的
const
-ness的替代:

const cpl *xx = &one;

完整节目:

#include <string.h>
#include <stdio.h>

typedef union {
  struct
  {
    int x;
    char *a;
    char *b;
    char *list[];
  };
  unsigned char lots_of_memory[100];
} cpl;

int main (void)
{
  static cpl one = { .x=1, .a="thisa", .b="thisb" };
  memcpy(one.list, (char*[]){ "one", "two", NULL }, sizeof(char*[3]));
  const cpl *xx = &one;

  for(size_t i=0; xx->list[i]!=NULL; i++)
  {
    puts(xx->list[i]);
  }
}

相当难看,但我真的想不出任何原因来解释为什么这段代码没有明确定义。 (如果有人这样做,请发表评论。)

© www.soinside.com 2019 - 2024. All rights reserved.