【问题标题】:How to initialise a pointer to pointer struct in C?如何在C中初始化指向指针结构的指针?
【发布时间】:2010-10-26 09:43:49
【问题描述】:

我有一个结构是一个节点,另一个是这些节点的列表。在 list 结构中,它是一个节点数组,但不是一个数组,而是一个指向具有大小整数的指针的指针:

typedef struct node {
    struct node *next;
    MyDef *entry;
} Node;


typedef struct list {
    Node **table;
    int size;
} List;

List *initialize(void)
{
    List *l;
    Node **n;

    if ((l = (List *)malloc(sizeof(List))) == NULL)
        return NULL;
    l->size = 11;

    /* I think this is correctly allocating the memory for this 'array' of nodes */
    if ((n = (Node **)malloc(l->size * sizeof(Node))) == NULL)
        return NULL;

    /* Now, how do I set MyDef *entry and Node *next to NULL for each of the 'array'? */

    l->table = n;

    return l;
}

如何将每个“数组”的 MyDef *entry 和 Node *next 设置为 NULL?

【问题讨论】:

标签: c arrays pointers malloc calloc


【解决方案1】:

(Node **) 是指向 [array of] Node 指针的指针,因此您分配的数组不会有任何结构成员。

您应该使用 (Node *),然后您将拥有 Node 结构的指向数组,或者分别分配每个 Node,然后将指向它们的指针放入您的数组中。

针对您的情况,标准 C 库中存在函数 calloc():它使用 0 初始化分配区域(对应于 (char/short/int/long)0、0.0 和 NULL)。

还有内存泄漏。

/* I think this is correctly allocating the memory for this 'array' of nodes */
if (... == NULL)
    return NULL;

当数组分配失败时,您不会释放 List,而是会丢失指向它的指针。改写为:

/* I think this is correctly allocating the memory for this 'array' of nodes */
if ((n = (Node **)malloc(l->size * sizeof(Node))) == NULL) {
    free(l);
    return NULL;
}

所以从我的观点来看,正确的代码应该是:

typedef struct node {
    struct node *next;
    MyDef *entry;
} Node;


typedef struct list {
    Node *table; /* (!) single asterisk */
    int size;
} List;

List *initialize(void)
{
    List *l;
    Node **n;

    if ((l = (MList *)malloc(sizeof(List))) == NULL)
        return NULL;
    l->size = 11;

    /* I think this is correctly allocating the memory for this 'array' of nodes */
    if ((n = (Node *)calloc(l->size, sizeof(Node))) == NULL)
    {
        free(l);
        return NULL;
    }

    /* Now, how do I set MyDef *entry and Node *next to NULL for each of the 'array'? */

    l->table = n;

    return l;
}

此外,C99 允许您制作可变大小的结构,因此您可以像初始化结构一样

typedef struct list {
    int size;
    Node table[0]
} List;

并根据需要在表中分配尽可能多的节点 malloc(sizeof(List) + sizeof(Node)*n);

【讨论】:

  • 非常感谢您抽出宝贵时间来做这件事。我正在尝试这个,因为我输入这个。
  • 刚试过这个,虽然这个位很好用,但我确实认为我需要 Node**。原因是,在程序的另一部分,我执行“n->next = (*l)->table[int val];”,其中 int val 是 size。如果没有 **,这不起作用,因为它不是数组?
  • n->next 是一个指向 Node 的指针,(l)->table[val] 是一个 Node,所以你必须得到指向它的指针。写 &((l)->table[val]) 或更短的 (l)->table+val (table+val 为您提供指向表的第 val 元素的指针)。 Node** 实际上将表示指向 Node 的指针数组,因此在这种情况下,您还应该为每个节点分配空间并将指向它的指针存储在数组元素中。
  • 感谢@Vovanium。最后一个错误:Node **n 应该是 Node *n 吗?否则 VS 2010 不喜欢“n = (Node *)calloc ...”。 VS 2010 也打破了“l->table = n;”?
  • 哦,你是对的,'Node *n' 是正确的,我在编辑源代码时错过了这个。
【解决方案2】:

首先,在我看来,您在分配数组的代码中有一个错误:它应该说 sizeof(Node*) 而不是 sizeof(Node) 因为您想要分配指向 Node 的指针数组而不是 Node 的数组对象。

然后就可以遍历数组列表了:

for ( unsigned i = 0; i < l->size; ++i )
{
    Node* node = l->table[ i ];
    node->entry = NULL;
    node->next = NULL;
}

另一个提示:您确实应该检查您的初始化函数是否存在内存泄漏的可能性。

【讨论】:

  • 谢谢,尝试了这个并得到一个错误:l->table CXX0030:错误:无法评估表达式
  • 知道为什么这不起作用吗? VS 2010 调试器在 Node* node = l->table[i]; 上中断
  • 我忘记了:还必须创建单个对象。但这似乎不是您的问题,因为错误已经发生在访问表的行中。但是,为了正确起见,需要l-&gt;table[i] = malloc(sizeof(Node)) 之类的东西。
  • 谢谢@Flinsch,我把那行放在 Node* node = ... 行之前,它仍然在 Node* node = ... 行上中断!
  • 在程序崩溃之前,您是否尝试过调试器在该行查看ll-&gt;table 的值?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-07-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多