【问题标题】:Using malloc in C to allocate space for a typedef'd type在 C 中使用 malloc 为 typedef 类型分配空间
【发布时间】:2011-05-14 05:22:06
【问题描述】:

我不确定我需要使用什么作为malloc 的参数来在table_allocate(int) 函数中分配空间。我只是在想count_table* cTable = malloc(sizeof(count_table*)),但这对 size 参数没有任何作用。我也应该为list_node_t 分配空间吗?下面是我正在使用的。

在 .h 文件中,我得到了这个签名:

//create a count table struct and allocate space for it                         
//return it as a pointer                                                        
count_table_t* table_allocate(int);

这是我应该使用的结构:

typedef struct list_node list_node_t;

struct list_node {
  char *key;
  int value;

  //the next node in the list                                                   
  list_node_t *next;
};

typedef struct count_table count_table_t;

struct count_table {
  int size;
  //an array of list_node pointers                                              
  list_node_t **list_array;
};

【问题讨论】:

  • 你已经得到了很多好的答案,但还没有人注意到重要的一点:int 是有符号类型,除非你想要负大小,否则你应该使用 @987654328 @,这是由sizeof 运算符返回并传递给malloc 和朋友的类型,旨在能够存储编译器允许的任何大小的数组的数组索引。你可能想要size_t size 而不是int size

标签: c malloc typedef dynamic-memory-allocation


【解决方案1】:
count_table* cTable = malloc(sizeof(count_table*))

错了。应该是

count_table* cTable = malloc(sizeof(count_table));

此外,您还必须为 list_node_t 单独分配内存。

编辑:

除了 Clifford 指出的为列表节点分配内存之外,我认为内存分配也应该注意列表节点内部的char *key

【讨论】:

  • 所以在函数中我可能应该 malloc 计数表,然后为 list_node_t 分配空间,然后将该列表节点放入计数表中?我做对了吗?
  • 是的。你做对了。 :) 但是,请参阅 Clifford 的关于 list_node_t 的双指针用法的回答。您需要检查为什么它在那里作为双指针给出。谢谢!
  • +1 但我会亲自写count_table* cTable = malloc(sizeof *cTable);
  • @Chris Lutz & Clifford,我同意你对此的看法。但是,我也多次看到人们打错字并错过了“*”,从而导致只分配了 4 个字节。这个问题导致在大代码中很难找到麻烦。所以,我对此有点困惑。
【解决方案2】:

您的建议:count_table* cTable = malloc(sizeof(count_table*)) 只会为 count_table 的 指针 分配空间。

你需要

count_table* cTable = malloc(sizeof(count_table) ) ;

每个列表节点将被单独分配,并且 cTable->size 和 cTable->list_array 和最后一个 list_node_t::next 会相应更新。保持指向最后添加的节点的指针会加快添加节点的速度。

我不确定为什么count_table::list_array 的类型是list_node_t** 而不仅仅是list_node_t*(同样称为list_array 而不仅仅是list)。你的意图是它同时是一个数组和一个列表吗?那会有些多余。成员只需要指向第一个节点的指针,然后通过list_node::next访问后续节点

【讨论】:

  • @detley:不,我的意思是 :: 因为左侧是类型而不是实例。我正在使用 C++ 范围表示法,尽管它不是代码,我只是将它用作表示结构成员而不是结构实例成员的表示法。在 C 中没有这样的语法方式。
  • 你说的很有道理。至于 (int size) 参数...您认为我打算在该函数中的 count_table 中添加这么多节点吗?我不明白 size 参数是干什么用的。
  • 我认为这个想法是有一个列表数组,所以当一个节点被散列时,你查看相关的数组条目,然后向下滚动一个单链表。这至少对数据结构有意义。
  • @Jonathan Leffler:听起来很可能。
【解决方案3】:

鉴于int 是创建的count_table_t 的“大小”参数,看来您应该既分配count_table_t 本身,也初始化其成员。

初始化list_array 成员还涉及内存分配,所以它看起来像:

count_table_t *table_allocate(int size)
{
    count_table_t *table = malloc(sizeof *table);
    int i;

    table->size = size;
    table->list_array = malloc(size * sizeof table->list_array[0]);
    for (i = 0; i < size; i++)
        table->list_array[i] = NULL;

    return table;
}

但是,您还需要检查一些错误情况:size 乘以 sizeof table-&gt;list_array[0] 可能会溢出,malloc() 调用中的任何一个都可能会失败。所以这个函数实际上应该是这样的:

count_table_t *table_allocate(int size)
{
    count_table_t *table;
    int i;

    /* Check for overflow in list allocation size */
    if (size < 0 || size > (size_t)-1 / sizeof table->list_array[0])
        return NULL;

    table = malloc(sizeof *table);

    if (table == NULL)
        return NULL;

    table->size = size;
    table->list_array = malloc(size * sizeof table->list_array[0]);

    if (table->list_array == NULL) {
        free(table);
        return NULL;
    }

    for (i = 0; i < size; i++)
        table->list_array[i] = NULL;

    return table;
}

(注意(size_t)-1 是一个常数,等于size_t最大值 值,这是malloc() 的参数类型)。

【讨论】:

  • 还要注意,OP 的int counts 应该都可能是size_ts。
  • @Chris Lutz:同意(这将消除对&lt; 0 检查的需要),但听起来函数签名和struct 定义是传下来的要求。
【解决方案4】:

除了其他海报指出你只是为指针分配了足够的空间,而不是你想要的数据将占用的空间,我强烈建议你这样做:

count_table* cTable = malloc(sizeof(*cTable));

这将在cTable 的类型发生变化时为您提供帮助,您无需调整该行的两个部分,只需调整类型即可。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-07-09
    • 2021-05-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-09
    • 2012-10-10
    • 2014-07-06
    相关资源
    最近更新 更多