[英]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.