C90中的可变长度结构

GNU C中允许零长度数组,因此可以进行初始化

struct line { int length; char contents[0]; }; struct line *thisline = (struct line *) malloc (sizeof (struct line) + this_length); thisline->length = this_length; 

注意:我在这里指的是这个页面: http : //gcc.gnu.org/onlinedocs/gcc/Zero-Length.html (提供C中可变长度结构的基本介绍)

它继续说:“在ISO C90中,你必须给内容一个长度为1,这意味着你要浪费空间或使参数复杂化到malloc。”

那是什么意思? 有人可以举例说明如何在C90中初始化变长结构以帮助理解吗?

如果你真的必须使用c90,那么C FAQ在问题2.6中有这个:

 struct name { int namelen; char namestr[1]; }; struct name *ret = malloc(sizeof(struct name)-1 + strlen(newname)+1); /* -1 for initial [1]; +1 for \0 */ 

虽然FAQ确实说:

目前尚不清楚它是合法的还是便携的,但它很受欢迎。 该技术的实现可能看起来像这样。

尽管gcc文档基本上表示它们支持它,但在C99中,FAQ表示他们添加了灵活的数组成员,我将在第6.7.2.1结构和联合说明符中 介绍的这个答案中介绍,并且有以下示例,与C90不同示例不需要特殊的数学来计算数组的大小:

 EXAMPLE After the declaration: struct s { int n; double d[]; }; the structure struct s has a flexible array member d. A typical way to use this is: int m = /* some value */; struct s *p = malloc(sizeof (struct s) + sizeof (double [m])); and assuming that the call to malloc succeeds, the object pointed to by p behaves, for most purposes, as if p had been declared as: struct { int n; double d[m]; } *p; (there are circumstances in which this equivalence is broken; in particular, the offsets of member d might not be the same). 

关于大小计算复杂性的评论涉及C与没有灵活arrays成员支持(即C90与C99)的基本区别。 在结构中使用单数元素数组时,该元素对sizeof()类型有贡献。 因此,用于真正灵活数组的灵活大小计算将不起作用:

在C90:

 struct name { int namelen; char namestr[1]; // contributes 1 + potential padding to sizeof(name) }; // using "the one" [1] as our terminator struct name *p = malloc(sizeof(name) + strlen(str)) 

而在C99中有一个灵活的成员

 struct name { int namelen; char namestr[]; // contributes no definitive value to sizeof(name) }; // specifying space for our terminator, since [] gives us nothing. struct name *p = malloc(sizeof(name) + strlen(str) + 1) 

如果你想知道关于没有空间贡献的评论,

C99§6.7.2.1结构和联盟规范

18作为一种特殊情况,具有多个命名成员的结构的最后一个元素可能具有不完整的数组类型; 这称为灵活的arrays成员。 在大多数情况下,忽略灵活的数组成员。 特别地,结构的尺寸好像省略了柔性arrays构件,除了它可以具有比遗漏所暗示的更多的拖尾填充。 ….

C90没有这样的细节,因此必须以不同的方式分配结构(并且可以说是未指定的方式,如果不是完全未定义的话)。