【问题标题】:Using flexible array member to implement a stack使用灵活的数组成员实现堆栈
【发布时间】:2021-02-01 05:09:55
【问题描述】:

使用这个结构:

typedef struct MyStack {
    size_t     size;      // current size of stack
    size_t     max;       // max size of stack
    Item*      data[];
} MyStack;

我该如何做一个正确的 malloc 然后 realloc ?例如,如果我这样做:

MyStack* stack = malloc(sizeof(MyStack));
stack->data  = malloc(size * sizeof(Item*));
// ... and later on...
stack->data = realloc(stack->data, new_stack_size);

我收到以下错误:

错误:灵活数组成员的使用无效
错误:灵活数组成员的使用无效(以上每一项都有一个错误)

那么,这样做的正确方法是什么?使用Item** data 而不是Item data[] 会更简单吗?

【问题讨论】:

  • 查看this answer 类似的问题。另请阅读 the Dragon bookGC handbook
  • 为什么不只是Item* data;?它是指向data 项目的指针。另外,为什么sizeof(Item*)?您没有为指针分配空间,是吗?
  • Item 是一个结构,所以我想要一个指向Item 的指针数组。抱歉,这个名字太笼统了,我可以改一下让它更清楚。
  • stackoverflow.com/questions/12680946/… 是相关的,可能会有所帮助。
  • @BasileStarynkevitch 很抱歉,这些书有什么关系?

标签: c malloc


【解决方案1】:

不,您不想为此使用灵活的数组成员(即data[];)。 Item *data[] 的分配是在分配整个MyStack相同 操作中完成的,因为Item *data[] 将位于它的末尾。

但是这对你的堆栈永远不起作用,因为大概你想在别处保存指向堆栈对象的指针。当您 realloc 时,之前指向 stackall 指针将变为无效(不确定是否准确)。否则,所有更改stack 的函数都必须始终将MyStack **stack 指向指针的指针作为参数,并且您只能对它有一个直接引用。

因此,您不想在这里使用灵活的数组成员。所以是的,如果数据项包含在堆栈中,则大部分只使用Item **data 甚至Item *data 会更简单。这意味着如上所述的双重间接,但在这种情况下处理起来会简单得多,您可以将MyStack *stack 传递给任何修改堆栈的函数。

附:总是将分配扩大一个因子而不是一个常数,这样每次插入操作的摊销插入成本是O(1)而不是O(n) ,即new_stack_size = new_stack_size * 5 / 4 + 1 什么的……

【讨论】:

  • 谢谢,您能否为上述问题提出一个更好的方法?
  • 只是为了澄清——当你说“扩大一个因子”时——你的意思是做 100 x 2 = 200 而不是 100 + 10 = 110。对吗?
  • @carl.hiass 是的。它在这两种情况下都能正常工作,但是如果你的堆栈是 1M 项,并且你重新分配到 1M+10 项,它需要在每添加 10 项后将这 1M 项复制到一个新的内存位置,这将是昂贵的。 stackoverflow.com/q/1100311/918959 讨论了最佳分配大小
猜你喜欢
  • 2018-03-29
  • 2015-08-17
  • 1970-01-01
  • 1970-01-01
  • 2020-10-24
  • 1970-01-01
  • 1970-01-01
  • 2012-03-16
  • 2012-09-22
相关资源
最近更新 更多