为什么在C中使用char * arr [1]?

时间:2016-05-20 15:58:09

标签: c

我遇到了以下代码。为什么使用*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) */
};

5 个答案:

答案 0 :(得分:4)

这是 struct hack 的示例,您可以在其中定义可变长度数组成员,而无需实际使用可变长度数组 1

这可能是最好的例子。假设struct类型

struct foo {
  int x;
  int arr[1];
};

如果我像这样分配一个结构实例:

struct foo f;

我为xint的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. 这很方便,因为VLA可能不是`struct`类型的成员。

答案 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块)。

祝你好运。