7

考虑以下 C 代码:

    #include <stdio.h>
    #include <stdlib.h>

    int main() {

        int arrSize;
        scanf("%d", &arrSize);
        printf("%d\n",arrSize);

        int *dynArr = (int *)malloc(sizeof(int)*arrSize);
        int arr1[arrSize];

        return 0;
    }

在上面的代码中,arrSize是取自用户输入的数组的大小。我想知道以下观察是否正确:

  • dynArr是一个动态数组,它在运行时在堆上分配到内存中。可以使用realloc函数修改 dynArr 的大小。

  • arr1在运行时也在内存中分配,但不是动态的(即它们的大小不能修改),它是在Stack上分配的。

4

4 回答 4

8

i) dynArr 是一个动态数组,它在运行时从堆部分分配内存。可以使用 realloc 函数修改 dynArr 的大小。

是的,如果realloc能找到足够大的块。尽管从技术上讲,指针不是数组。它指向数组第一个元素。

ii)。arr1 也在运行时分配内存,但不是动态的,即它们的大小不能修改。内存是从堆栈或数据部分分配的。(不确定从哪个部分堆或堆栈/数据分配内存以及为什么)。

数组的大小是动态的,它的生命周期不是。它将在返回的那一刻自动回收main。可变长度数组通常分配在调用堆栈上。是的,一旦你宣布它,你就不能改变它的大小。


如果您现在想知道何时使用其中一个而不是另一个,则需要考虑以下几点:

  1. 为调用堆栈保留的内存是有限的(远远超过堆)。如果在其上声明一个巨大的 VLA,很容易溢出。

  2. malloc从及其亲属返回的内存可以比分配它的堆栈帧长。

  3. 通常,分配 VLA 比使用malloc. 一个是堆栈帧指针的简单进展,而另一个涉及堆的内存分配器及其逻辑。

于 2017-01-02T07:56:33.373 回答
4

dynArr是一个动态数组,它在运行时从堆部分分配内存。dynArr可以使用realloc函数修改大小。

  • dynArr是一个指针,它使用返回的指针初始化malloc()。请记住,数组不是指针,反之亦然。在某些情况下,数组名称衰减为指向数组第一个元素的指针,但这并不能使两者相同。

  • size ofdynArr是指针的大小,而不是它指向的内存位置的大小。使用正确的单词, in 可以表示为,它指向的内存大小可以使用 来更改realloc()

arr1在运行时也分配了内存,但不是动态的,即它们的大小不能修改。内存是从堆栈或数据部分分配的。(不确定从哪个部分堆或堆栈/数据分配内存以及为什么)。

这称为变长数组。其他点是正确的。

引用C11,第 6.7.6.2 章

如果 size 是一个不是整数常量表达式的表达式:如果它出现在函数原型范围的声明中,则将其视为被 * 替换;否则,每次对其进行评估时,它的值都应大于零。可变长度数组类型的每个实例的大小在其生命周期内不会改变。

于 2017-01-02T07:57:35.160 回答
2

它从空闲内存存储中分配内存。现在,在 C 的情况下,内存中没有所谓的堆和堆栈......这是我们在逻辑上考虑的东西C。(在 C 的实现中)]


唯一让我们烦恼的是我们是否需要你想要活着的东西,即使它被声明的范围是否结束。

对于堆,情况是这样。对于堆栈,情况并非如此。

在你的情况下

int arr1[arrSize];分配在存储此主函数局部变量的同一帧上。

动态分配

您可以控制这些内存位置的确切大小和生命周期。如果您不释放它,您将遇到内存泄漏,这可能会导致您的应用程序崩溃,因为它在某些时候无法分配更多内存。( dynArr)

实际上...

堆是计算机内存的一个区域,它不会自动为您管理,也不是由 CPU 严格管理。它是一个更自由浮动的内存区域(并且更大)。要在堆上分配内存,您必须使用 malloc() 或 calloc(),它们是 C 的内置函数。

一旦你在堆上分配了内存,你有责任在你不再需要它时使用 free() 来释放该内存。如果你不这样做,你的程序就会发生所谓的内存泄漏。也就是说,堆上的内存仍将被留出(并且不会对其他进程可用)。

它是计算机内存的一个特殊区域,用于存储每个函数(包括 main() 函数)创建的临时变量。堆栈是一种“LIFO”(后进先出)数据结构,由 CPU 密切管理和优化。每次函数声明一个新变量时,它都会被“推入”堆栈。然后每次函数退出时,所有被该函数压入堆栈的变量都被释放(也就是说,它们被删除)。释放堆栈变量后,该内存区域可用于其他堆栈变量。

资源

于 2017-01-02T07:55:22.240 回答
1

实际上,Google C++ Style Guide 中不允许变长数组。它的语法看起来很自然,而且效率很高,但是,由于它们分配了与数据相关的堆栈空间量,它可能会引发严重而神秘的内存覆盖错误:

有时“它在我的机器上运行良好,但在生产中神秘地死了”。

于 2017-01-02T08:24:11.197 回答