不使用Malloc分配结构体数组?

5

我有一个按照如下方式定义的结构体。

typedef struct COUNTRY {
    char Code[3];
    char Country[30];
    int Population;
    float Expectancy;
    struct Country *Pointer;
} COUNTRY;

我看到过这样分配的结构体数组:

COUNTRY *countries = calloc(128, sizeof(COUNTRY));

也许可以这样做:
COUNTRY *countries = malloc(128 * sizeof(COUNTRY));

但这句话是什么意思:

COUNTRY countries[128] = {};

因为我仍然能在所有情况下写入每个条目的字段。第三个选项只是不好的形式吗?对我来说,它似乎更好,因为你可以将那行代码与其余变量声明放在 main() 之外。否则,你只能在 main() 或其他函数中使用 calloc() 或 malloc()。 我做错了什么吗?
5个回答

6

This:

COUNTRY countries[128];

这句话简单地定义了一个类型为"128个COUNTRY元素的数组"的对象。

= {}是一个初始化器,但是在C语言中空的初始化器是不合法的(我认为gcc支持它们作为扩展)。一个可移植的替代方法是:

COUNTRY countries[128] = { 0 };

该数组初始化所有元素的成员为零(对于整数是0,对于字符是\0',对于浮点数是0.0,对于指针是NULL,以及递归地应用于子元素)。但由于您指定了数组中元素的数量(为128),因此初始化程序不会影响分配数组对象的方式。
如果声明出现在函数定义内部,则数组对象具有自动存储期限,这意味着当执行到封闭块的结尾时,它将停止存在。这些对象通常在“堆栈”上分配。
如果它出现在任何函数定义之外(在文件作用域或者如果它具有关键字static,则它具有静态存储期限,这意味着它在程序的整个执行过程中都存在。
使用malloccalloc分配的对象具有分配存储期限,这意味着它们会继续存在,直到通过调用free()进行明确释放。这些对象通常在“堆”上分配。(我忽略了realloc(),它稍微复杂了一些的描述。)

3
前两个语句将在堆上分配结构体数组,而最后一个语句将在栈上初始化结构体数组。
这并不是一种不好的形式,只是关乎您希望数据存储在哪里 - 在栈上(当变量超出作用域时自动释放,栈通常比堆小得多,因此如果将大型数据结构放在那里可能会溢出),还是在堆上(数据的生命周期与作用域无关,需要手动释放内存)。

对我来说,这似乎更好,因为您可以将该行与main()之外的其余变量声明放在一起。

如果您需要具有程序生命周期的静态分配对象,请使用此方法,这没有任何问题。请注意,在这种特定情况下,变量不是存储在栈上,而是存储在程序的.data段中(有关更多详细信息,请查看此问题:全局变量如何存储?)。

除了寿命差异之外,在许多系统中,堆栈大小比堆大小小得多,因此许多人倾向于避免在堆栈上分配大型数组。 - Laurence Gonsalves

0
最后一种形式是“堆栈分配”或“静态分配”。与calloc类似,所有字段都将被清零。
在函数内部,它是“堆栈分配的”,当函数返回时,该内存将消失。
在任何函数之外,在文件范围内,它是静态分配的,并且是在main()开始之前分配的全局内存块。

0

在编译时不知道需要多少内存时,可以使用malloc/calloc。例如,在链表中,需要动态分配/释放节点。当您使用数组时,您在编译时就知道需要多少内存。

另一个不同之处是内存的来源。如果在函数中声明一个数组,则内存将来自堆栈。对于malloc/calloc,内存将在中设置。


0

= {};

是GNU C扩展,与以下代码相同:

= {0};


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接