繁体   English   中英

为什么我们需要在 C 中为数组使用 malloc() 或任何其他动态内存?

[英]Why do we need to use malloc() or any other Dynamic Memory for ARRAYS in C?

考虑C 中的这些代码:

int n;  
scanf("\n%d ",&n);  
int arr[n];

和这个。

int n;
scanf("\n%d ",&n);
int *p = (int *)malloc(n*sizeof(int));  

为什么我们首先需要为此进行动态内存分配?
第一个代码不是动态内存分配,因为数组是在运行时创建的?

我什么时候应该使用 malloc()?

int arr[n]; 在堆栈上分配内存 它会自动分配,然后在块的末尾解除分配 无法从函数安全地返回指向堆栈内存的指针。

考虑一下。

#include <stdio.h>

char *make_array() {
    int n;  
    scanf("%d",&n);

    // Memory for `arr` is allocated on the stack.
    char arr[n];

    // And then deallocated when the function exits.
    // A good compiler and editor will warn you if you try
    // to return it.
    return arr;
}

int main() {
    // This pointer is to memory which has already been freed. Other things
    // will overwrite it.
    char *arr = make_array();

    arr[0] = 'c';
    arr[1] = '\0';

    // This could be the letter c, but it's probably gibberish.
    puts(arr);
}

如果您需要内存超过当前函数的生命周期,则需要使用malloc将其分配到堆上并malloc管理。

只是为了确保您理解:

当“函数调用函数”时,它们的局部变量存储在称为“堆栈”的内存区域中,之所以如此命名,是因为它的工作方式类似于下推式 LIFO 堆栈。 当进入一个函数时,堆栈会增长。 当函数返回时,它会收缩。 如果一个函数递归调用自身,则不会出现混淆,因为每个实例在堆栈上都有自己的区域。

malloc() “应请求”从称为“堆”的不同区域分配内存,之所以如此命名是因为它没有特定的内置组织。 这些内存区域是使用“指针”间接引用的指针是其值被理解为内存地址的变量。

“C”语言允许您在使用指针时方便地使用“数组表示法”,就像它在堆栈上分配的局部变量一样。

int n;  
scanf("\n%d ",&n);  
int arr[n];

如果它有效,那么这意味着您使用的编译器仍然将其解释为“DMA” ,唯一的区别是它会在范围结束时被释放,但我认为这对 C 来说不是一个好习惯。

int n;  
scanf("\n%d ",&n);  
int arr[n];

其中n是运行时动态值(在本例中是这样)在旧版本的 C 中不受支持,这要求n是整数常量表达式。

现代版本的 C 已经解除了这个限制,允许动态大小的数组(可变长度数组,或 VLA),但与旧的固定大小的数组不同,VLA 有限制。

不允许跳过它们(使用break / continue / goto ),它们可能不是异步信号安全的,如果它们太大,它们会使您的程序崩溃,并且它们通常会生成比普通旧代码更大的代码本地数组。

此外,因为它们是本地的,您不能将指向它们的指针返回给您的调用者。

大小限制是他们最大的限制之一。 VLA 是从调用堆栈中划分出来的,它通常只有几千/兆字节大,如果超出此限制,您通常会遇到未诊断的崩溃。

malloc的内存没有这样的限制, malloc失败通过返回的NULL清楚地报告,并且因为malloc的内存对进程来说是全局的,您可以将指向它的指针传回给您的调用者。

`

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM