我有一个看起来像这样的结构。
struct MyStruct1 {
int (*fn)();
int b;
}
另一个看起来像这样的结构。
struct MyStruct2 {
int a;
struct MyStruct1 b[0];
}
我想声明MyStruct2类型的全局变量,有点像这样。
int func1() { return 1; }
int func2() { return 2; }
struct MyStruct2 a = { 1, { func1, 5 }, { func2, 6 } };
但是,我得到一个“初始化元素不是编译时常量”。
我想知道(a)是否有可能全局声明一个可变大小的结构(或者至少定义一个空格块,大小正确,以便稍后插入值),以及(b)如果是的话,我做错了什么?
答案 0 :(得分:0)
您无法合法地在C中创建大小为0的数组。在C99或C11中,您可以使用灵活的阵列成员'像这样:
struct MyStruct2 {
int a;
struct MyStruct1 b[];
};
但是具有灵活数组成员的结构只能通过动态内存分配来创建(其他形式的分配会为您提供一个大小为0的不可用的灵活数组)。
旧的'结构黑客'具有可变大小数组的结构的版本在结构中使用大小为1的数组。您可以使用大小为1的数组创建此类结构的全局版本。
但基本上,你正试图做语言禁止你做的事情,而且非常令人惊讶的是,你失败了。
您对此采取的措施取决于您的需求。全局变量本身就有些不受欢迎,所以有一个元素是"你应该试图避免这样做"。也就是说,规则也适用于文件范围(static
)变量,并且这些变量有很多用途。
您可以使用显式指针代替数组,并对struct MyStruct2
的主体及其struct MyStruct1
成员数组进行单独分配。您可以放弃全局变量,并使用灵活的数组成员使用动态分配的结构。
struct MyStruct2 *ms2 = malloc(sizeof(*ms2) + N * sizeof(ms2->b[0]));
这会在数组中创建一个struct MyStruct2
(如本答案顶部所示),其中包含N
个成员。如果没有任何进一步的更改,您可以使用ms2->b[0]
到ms2->b[N-1]
(除了错误检查malloc()
成功之外)。
答案 1 :(得分:0)
无法在本地或全局声明可变大小struct
。每种类型都有一个在编译时确定的固定大小。
但是,您报告的错误消息令人惊讶。如果您提供的所有声明都在文件范围内,在同一文件中,按照您给出的顺序,那么变量a
的初始化程序是编译时常量。但是,它不是struct MyStruct2
,
struct
类型具有成员的元素,a.b
的初始值设定项元素是struct MyStruct1
的初始值设定项,而不是数组的初始值设定项,a.b
中的元素(即大于零)。如果你想要一个动态大小的数组,无论是作为一个变量本身还是作为struct
的成员,那么你必须声明一个指向它的指针,并动态地为这些元素分配内存。在这种情况下,元素本身不是struct
的一部分;只有指向它们的指针是。 (顺便说一句,这与固定大小的数组不同,后者的大小在其初始化程序中是隐式的;但这些数据仅适用于独立类型,不适用于struct
或union
成员的类型。
修改强>
正如ShafikYaghmour评论的那样,C99柔性阵列是一种可能的替代方案。它们与struct
元素类似但不相同,后者是指向动态分配数组的指针。但是,在这种情况下,您不仅无法静态声明数组元素,还无法静态声明struct
本身的实例,因此这根本不会解决您的初始化程序问题。还有其他一些怪癖和限制。我个人认为灵活数组没有什么优势,但它们确实使得正确释放struct实例变得容易一些。