【问题标题】:Why does static initialization of flexible array member work?为什么灵活数组成员的静态初始化有效?
【发布时间】:2015-03-07 06:32:04
【问题描述】:

我为菜单编写了以下基本代码:

typedef struct Menu {
    char* title;
    unsigned num_submenus;
    struct Menu *submenu[];
} Menu;

Menu sub1 = {"Submenu 1", 0, {NULL}};
Menu sub2 = {"Submenu 2", 0, {NULL}};
Menu Main = {"Main Menu", 2, {&sub1, &sub2}};   /* No Error?! */

int main()
{
    printf("%s\n", Main.title);
    printf("%s\n", Main.submenu[0]->title);
    printf("%s\n", Main.submenu[1]->title);
}

浏览几个相关问题,似乎使用灵活数组成员的唯一方法是动态为其分配内存。但是,我的编译器非常乐意编译和运行代码而不会出现任何错误或警告。这是禁止的吗?

我正在使用 MinGW gcc 4.6.1 并在 C99 规则下编译。

【问题讨论】:

  • 您期待什么错误?
  • 你是否使用-pedantic编译会报错。
  • clang++ 11.0.0 给出:error: initialization of flexible array member is not allowed

标签: c gcc struct initialization flexible-array-member


【解决方案1】:

根据 C 标准,不允许以这种方式初始化灵活数组成员。

C11:6.7.2.1 结构和联合说明符 (p20-21):

21 示例 2 声明后:

struct s { int n; double d[]; };

结构结构s 有一个灵活的数组成员d。 [...]

22 按照上述声明:

struct s t1 = { 0 }; // valid
struct s t2 = { 1, { 4.2 }}; // invalid
t1.n = 4; // valid
t1.d[0] = 4.2; // might be undefined behavior

t2 的初始化无效(并且违反了约束),因为 struct s 被视为不包含成员 d。 [...]

但是,GCC 允许对灵活数组进行静态初始化:

GCC Manual: 6.17 Arrays of Length Zero:

GCC 允许灵活数组成员的静态初始化。这相当于定义一个包含原始结构的新结构,后跟一个足够大的数组来包含数据。例如。在下文中,f1 的构造就像它被声明为 f2

 struct f1 {
   int x; 
   int y[];
 } f1 = { 1, { 2, 3, 4 } };

 struct f2 {
   struct f1 f1; 
   int data[3];
 } f2 = { { 1 }, { 2, 3, 4 } };

【讨论】:

  • 啊,是的,“静态”是我缺少的词。无论如何,除 GCC 之外的其他编译器是否允许使用此代码?
  • @thndrwrks;查看更新。标准不允许灵活数组的静态初始化。
  • @nyholku; n1570:§6.7.2.1/18*[...]在大多数情况下,灵活数组成员被忽略。特别是,结构的大小就像省略了灵活数组成员一样,只是它可能具有比省略所暗示的更多的尾随填充。[...]*
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-10-27
  • 1970-01-01
  • 2013-10-19
  • 2011-08-04
  • 2013-04-13
  • 2015-02-18
相关资源
最近更新 更多