我遇到了以下代码。为什么使用*child[1]
代替*child
?
struct _zend_ast {
zend_ast_kind kind; /* Type of the node (ZEND_AST_* enum constant) */
zend_ast_attr attr; /* Additional attribute, use depending on node type */
uint32_t lineno; /* Line number */
zend_ast *child[1]; /* Array of children (using struct hack) */
};
答案 0 :(得分:4)
这是 struct
hack 的示例,您可以在其中定义可变长度数组成员,而无需实际使用可变长度数组 1 。
这可能是最好的例子。假设struct
类型
struct foo {
int x;
int arr[1];
};
如果我像这样分配一个结构实例:
struct foo f;
我为x
和int
的1元素数组提供了足够的空间:
+---+
x: | |
+---+
arr: | | arr[0]
+---+
不是非常有用。
但是,如果我像这样为结构分配空间:
struct foo *p = malloc( sizeof *p + (4 * sizeof( int ));
我得到这样的东西:
+---+
x: | |
+---+
arr: | | arr[0]
+---+
| | arr[1]
+---+
| | arr[2]
+---+
| | arr[3]
+---+
| | arr[4]
+---+
我为结构的所有成员分配了足够的空间,并为另外4个整数分配空间。这个额外空格位于arr
之后,这意味着我已经有效地创建了p->arr
作为{em> 5 元素int
的数组。好像我已经将结构定义为
struct foo {
int x;
int arr[5];
};
这与
这样的技术截然不同struct bar {
int x;
int *arr;
};
struct bar *p = malloc( sizeof *p );
if ( p )
{
p->arr = malloc( sizeof *p->arr * 5 );
}
给我这样的东西:
+---+
x: | |
+---+
arr: | | ---------+
+---+ |
... |
+---+ |
| | arr[0] <-+
+---+
| | arr[1]
+---+
| | arr[2]
+---+
| | arr[3]
+---+
| | arr[4]
+---+
arr
的内存不属于struct
实例本身; struct bar
的每个实例大小相同
答案 1 :(得分:0)
因为这表示“指向zend_ast的指针数组”而不是“指向zend_ast的数组(指针)”。另一个,恕我直言更可读的方式来写一些具有相同效果的东西(虽然在语义上不是完全相同)将是zend_ast **child
。
答案 2 :(得分:0)
结构的作者似乎将使用未定义大小的数组。也就是说,结构可以具有可变大小,具体取决于结构的最后一个数据成员(数组)将具有多少元素。
最后一个数据成员也可以声明为灵活数组。
答案 3 :(得分:0)
也许作者希望能够将该成员用作数组I.e.传递给期望数组的函数,传递地址而不是值...
答案 4 :(得分:0)
作者显然希望最后一个元素是一个可变大小的'pointers-to-_zend_ast'数组。在诸如此类的方案中,通常在数组的最后一个指针中使用NULL值作为“数组结束”标记。另一种选择是将child
定义为zend_ast **
,然后指向一个完全独立的内存块。后一种安排有点复杂且容易出错,因为在释放内存时必须释放两个内存块(struct _zend_ast
块和child
块)。
祝你好运。