结构中的成员的顺序是否重要?

我在C中发现了一个奇特的行为。考虑下面的代码:

struct s { int a; }; struct z { int a; struct sb[]; }; int main(void) { return 0; } 

它编译得很好。 然后像这样改变struct z成员的顺序

 struct z { struct sb[]; int a; }; 

突然之间,我们得到的编译错误field has incomplete type 'struct s []'

这是为什么?

struct中字段的顺序很重要 – 编译器不允许对字段重新sorting,所以struct的大小可能会因添加一些填充而改变。

然而在这种情况下,你正在定义一个所谓的灵活的成员 ,一个你可以改变大小的数组。 灵活的成员规则是这样的

  • 可能永远不会有一个以上的这样的成员,
  • 如果存在,灵活的成员必须是结构中的最后一个,并且
  • struct必须至less有一个成员除了灵活的一个。

看一下这个问答关于使用灵活的结构成员的小插图。

编译器不能计算多less内存struct sb[]; 会消耗。 这意味着如果结构体之后有任何字段,编译器就无法弄清楚这些字段在哪里。

它曾经是(在旧版本的C),(例如) struct sb[]; 不被允许作为一个结构的成员。 这使得高效的内存pipe理变得烦人。 举一个简单的例子,假设你有一个包含“name”string的结构(可能只是几个字符或者很多)。 你可以使用一个固定大小的数组,这个数组对于最大的名字是足够大的(浪费空间),或者使用一个指针并分配2个内存(一个用于结构,另一个用于可变长度名string)。 或者,你可以使用一个指针,并使其指向结构末端的额外空间,结果如下所示:

  length = strlen(my_string); foo = malloc(sizeof(MYSTRUCTURE) + length + 1); foo->name = (void *)foo + sizeof(MYSTRUCTURE); // Set pointer to extra bytes past end of structure memcpy(foo->name, my_string, length + 1); 

这是最有效的select; 但它也是丑陋的和容易出错的。

为了解决这个问题,编译器添加了非标准的扩展以允许在结构的末尾使用“未知大小的数组”。 这对程序员来说更简单一些,并且使其效率更高一些(因为不需要额外的指针成员)。 这最终被C标准采用(可能在C99中 – 我不记得了)。

成员的顺序通常很重要(即可能会在字段之间插入一些填充),但在具体情况下,您使用的是灵活的成员数组,这在C99-6.7.2.1.16

作为特殊情况,具有多个名称成员的结构的最后一个元素可能具有不完整的数组types; 这被称为一个灵活的数组成员。 在大多数情况下,灵活的数组成员被忽略。 特别是,结构的大小就好像是柔性arrays成员被省略,除了它可能具有比省略暗示的更多的尾部填充。

你的struct sb[]; 成员是用来访问多个struct s元素的dynamic堆分配。

你的问题的标题是“ struct的成员的顺序是否重要?”。

代码中的明显问题与您的struct包含灵活成员的事实有关。

所以这是一个与struct中成员顺序的一般问题有关的额外问题:


以下面两个结构为例:

 struct s1 { int a; short b; char c; }; struct s2 { char c; short b; int a; }; 

大多数编译器都会添加填充,以便将每个成员alignment到可以被大小整除的地址。

所以struct s2最终可以编译成:

 struct s2 { char c; char pad1; short b; short pad2; short pad3; int a; }; 

这最终将导致types为struct s1struct s2实例的大小不同。

在这种情况下,订单确实很重要。 你的struct z包含一个由structs s struct z组成的数组。 但是,这个数组没有与它相关的大小,所以编译器不知道如何分配适当的堆栈空间,因为之后还有另一个struct( int a )字段。 一个如何工作的例子:

 struct s { int a; } struct z { struct sb[10]; int a; } int main(void) { return 0; } 

如果你真的需要数组来改变大小,最好的办法是把整个结构分配给堆,把数组作为struct s的指针,然后dynamic地重新分配它以适应不断变化的数组大小。 查找malloc (3)realloc 3)calloc (3)free (3)