21

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

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 规则下编译。

4

1 回答 1

21

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

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

21 示例 2 声明后:

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

结构 structs具有灵活的数组成员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它被视为不包含 member d。[...]

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

GCC 手册:6.17 长度为零的数组

相反,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 } };
于 2015-01-09T00:38:35.213 回答