C动态分配结构数组及其组件

时间:2018-11-27 08:53:28

标签: c arrays struct dynamic-memory-allocation

在C中动态分配结构数组及其组件的正确方法是什么?我已经做了一些行之有效的事情,但是我对它是否正确表示怀疑。 我有以下代码:
这是我需要动态分配的struct数组:

k

这是我需要初始化结构数组时调用的函数:

typedef struct
{
    char *wrong;
    char *right;
}Dictionary;

然后在我的主要功能中,我有这个:

Dictionary *init_Dictionary(int nr_elem)
{
    Dictionary *dict;
    dict = malloc(nr_elem*sizeof(Dictionary));
    for(int i=0; i<nr_elem; i++)
    {
        char wrong[101],right[101];
        scanf("%s%s",wrong,right);
        dict[i].wrong = malloc(strlen(wrong)*sizeof(char));
        dict[i].right = malloc(strlen(right)*sizeof(char));
        strcpy(dict[i].wrong,wrong);
        strcpy(dict[i].right,right);
    }
    return dict;
}

此外,当我完成该结构的工作时,如何释放已使用的内存?
编辑,谢谢大家的快速而深入的解答!

3 个答案:

答案 0 :(得分:3)

对于每个分配,您需要再分配一个位置,以允许在字符串末尾使用\0(NULL终止符)。

dict[i].wrong = malloc(strlen(wrong)*sizeof(char) +1 );
dict[i].right = malloc(strlen(right)*sizeof(char) +1);

要释放,首先需要释放数组中的所有指针rightwrong,然后释放主dict数组。 (可选)您可以在释放指针之后使指针为NULL。

Dictionary* freeDict(Dictionary *dict, int nr_elem)
{
    for (int i=0; i<nr_elem; i++)
    {
        free(dict->wrong);
        free(dict->right);
        dict->wrong = NULL;
        dict->right = NULL;
    }
    free (dict);
    dict = NULL;
    return dict;
}

//To call.
dict = free(dict, nr_elem);

答案 1 :(得分:2)

程序设计不好,应该将UI与算法分开。取而代之的是,您应该首先接受用户输入,然后将其存储在2个字符串中,并将字符串作为参数传递给init_Dictionary

关于分配,这几乎是正确的。但是您忘记为空终止符分配空间,它应该是:

dict[i].wrong = malloc(strlen(wrong)+1);
dict[i].right = malloc(strlen(right)+1);

sizeof(char)相乘是没有意义的,因为在所有系统上sizeof(char)的定义始终为1

在生产质量的应用程序中,您必须始终检查每个malloc的结果,然后处理错误。

您以与分配内存相同的方式释放内存,但是顺序相反,因为您需要dict本身才有效,直到您释放其成员为止:

for(int i=0; i<nr_elem; i++)
{
  free(dict[i].wrong);
  free(dict[i].right);
}
free(dict);

根据经验,每次对malloc的调用都必须与对free的调用相匹配。

答案 2 :(得分:2)

您的实现中存在一个错误:strlen(s)不计算终止的0字符,因此,尽管一个测试可能成功完成,但实际上这是一个UB。 strdup可以为您服务;如果您没有标准库,只需为字符串副本分配内存时加1。甚至更好:将字符串长度计算一次,然后使用该值分配足够的字节并使用memcpy复制内容。

否则,您的算法将非常有用(只要您真正需要字符串对数组即可,而无需使用诸如搜索索引之类的其他结构即可。)

要对其进行释放,请添加一个执行逐个元素的释放的析构函数,然后释放整个数组:

void destroy(Dictionary *dict, size_t nr_elem) {
    for(size_t i = 0; i < nr_elem; ++i) {
        free(dict[i].wrong);
        free(dict[i].right);
    }
    free(dict);
}