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()。

难道我做错了什么?

4

5 回答 5

6

这个:

COUNTRY countries[128];

简单地定义一个对象,其类型是“128 个COUNTRY元素的数组”。

= {}是一个初始化器——但空初始化器在 C 中是非法的(我认为 gcc 支持它们作为扩展)。便携式替代方案是:

COUNTRY countries[128] = { 0 };

它将所有元素的所有成员初始化为零(0对于整数,\0'对于字符,0.0对于浮点数,NULL对于指针,对于子元素递归)。但是由于您指定了数组中的元素数量(as 128),所以初始化程序对数组对象的分配方式没有影响。

如果声明发生在函数定义中,则数组对象具有自动存储持续时间,这意味着当执行到达封闭块的末尾时它不再存在。此类对象通常分配在“堆栈”上。

如果它出现在任何函数定义之外(在文件范围内或者如果它有关键字static,那么它具有静态存储持续时间,这意味着它在程序的整个执行过程中继续存在。

malloc已分配或calloc分配 storage duration的对象,这意味着它们将继续存在,直到通过调用free(). 此类对象通常分配在“堆”上。(我忽略realloc()了,这使描述有点复杂。)

于 2013-09-19T18:03:06.283 回答
3

前两个语句将在堆上分配结构数组,而最后一个语句将在堆栈上初始化结构数组。

这不是一个糟糕的形式,这只是您希望将数据存储在哪里的问题 - 在堆栈上(当您的变量超出范围时自动释放,堆栈的大小通常比堆小得多,因此您可能会溢出它如果您将大数据结构放置在那里),或者在堆上(数据的生命周期与范围无关,您需要手动释放内存)。

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

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

于 2013-09-19T18:01:33.780 回答
0

最后一种形式是“堆栈分配”或“静态分配”。像 calloc 一样,所有字段都将被清零。

在函数内部,它是“堆栈分配的”,当函数返回时,该内存将消失。

在任何函数之外,在文件范围内,它是静态分配的,并且在 main() 开始之前分配了一块全局内存。

于 2013-09-19T18:02:14.140 回答
0

当您在编译时不知道需要多少时使用 malloc/calloc。例如,在链表中,您需要动态分配/取消分配节点。当你使用一个数组时,你就知道在编译时你需要多少。

不同的是从哪里获取内存。如果在函数中声明数组,则内存将从堆栈中取出。在 malloc/calloc 的情况下,内存在堆中留出。

于 2013-09-19T18:03:31.427 回答
0

= {};

是 GNU C 扩展,与以下内容相同:

= {0};

于 2013-09-19T18:11:56.297 回答