我想知道静态内存分配和动态内存分配之间的区别是什么?
你能用任何例子解释一下吗?
我想知道静态内存分配和动态内存分配之间的区别是什么?
你能用任何例子解释一下吗?
Answers:
共有三种类型的分配-静态,自动和动态。
静态分配是指在程序启动时分配变量的内存。创建程序时大小是固定的。它适用于全局变量,文件范围变量和使用static
内部函数定义的合格变量。
自动内存分配发生在函数内部定义的(非静态)变量上,并且通常存储在堆栈中(尽管C标准并不要求使用堆栈)。您不必使用它们来保留额外的内存,但是,另一方面,对这些内存的生存期的控制也很有限。例如:函数中的自动变量仅在函数完成之前存在。
void func() {
int i; /* `i` only exists during `func` */
}
动态内存分配有些不同。现在,您可以控制这些内存位置的确切大小和生存期。如果不释放它,则会遇到内存泄漏,这可能导致您的应用程序崩溃,因为在某些时候,系统无法分配更多的内存。
int* func() {
int* mem = malloc(1024);
return mem;
}
int* mem = func(); /* still accessible */
在上面的示例中,即使函数终止,分配的内存仍然有效且可访问。内存用完后,您必须释放它:
free(mem);
这是一个标准的面试问题:
是存储在系统运行时分配的calloc()
,malloc()
和朋友。尽管它与堆数据结构ref无关,但有时也称为“堆”内存。
int * a = malloc(sizeof(int));
堆内存是持久的,直到free()
被调用为止。换句话说,您可以控制变量的生存期。
这就是通常所说的“堆栈”内存,当您输入新的作用域时(通常是在调用堆栈上推送新功能时)进行分配。移出作用域后,自动内存地址的值是不确定的,访问它们是错误的。
int a = 43;
注意,范围不一定表示功能。作用域可以嵌套在一个函数中,并且变量仅在声明它的块内是作用域内的。另请注意,未指定分配此内存的位置。(在理智的系统上,它将在堆栈上,或者进行优化注册)
在编译时*分配,并且静态存储器中变量的生命周期是程序的生命周期。
在C语言中,可以使用static
关键字分配静态内存。范围仅是编译单位。
当extern
考虑关键字时,事情变得更加有趣。当extern
变量被定义为它的编译器分配存储器。当一个extern
变量声明,编译器要求变量被定义在别处。声明/定义extern
变量失败将导致链接问题,而声明/定义static
变量失败将导致编译问题。
在文件范围内,static关键字是可选的(在函数外部):
int a = 32;
但不在函数范围内(在函数内部):
static int a = 32;
从技术上讲,extern
和static
是C中两个独立的变量类。
extern int a; /* Declaration */
int a; /* Definition */
说静态内存是在编译时分配的,这有点令人困惑,尤其是如果我们开始考虑编译机和主机可能不相同,甚至可能不在同一体系结构上时。
最好认为静态内存的分配是由编译器处理的,而不是在编译时进行分配。
例如,编译器可能会data
在已编译的二进制文件中创建一个较大的节,并且当程序被加载到内存中时,该地址位于data
该程序的段将用作分配的内存的位置。这具有明显的缺点,如果使用大量静态内存,则使已编译的二进制文件非常大。可以编写由不到六行代码生成的数千兆字节的二进制文件。编译器的另一种选择是在执行程序之前注入将以其他方式分配内存的初始化代码。该代码将根据目标平台和操作系统而有所不同。在实践中,现代编译器使用启发式方法来决定使用这些选项中的哪一个。您可以编写一个小的C程序来自己尝试一下,该程序为10k,1m,10m,100m,1G或10G项分配一个大型静态数组。对于许多编译器,二进制大小将随着数组的大小线性增长,并超过特定点,
最后一个内存类是“寄存器”变量。正如预期的那样,应该在CPU的寄存器上分配寄存器变量,但实际决定权留给了编译器。您不能使用address-of将寄存器变量转换为引用。
register int meaning = 42;
printf("%p\n",&meaning); /* this is wrong and will fail at compile time. */
在选择应将哪些变量放入寄存器中时,大多数现代编译器比您聪明:)
int * a = malloc(sizeof(*a));
您避免重复输入的类型a
。如果进行a
更改的类型,这将使事情变得容易得多。
静态内存分配:编译器为声明的变量分配所需的内存空间。通过使用运算符的地址,可以获取保留地址,并且可以将该地址分配给指针变量。由于大多数声明的变量都具有静态内存,因此将指针值分配给指针变量的方法称为静态内存分配。在编译期间分配了内存。
动态内存分配:它使用malloc()或calloc()之类的函数动态获取内存。如果使用这些函数动态获取内存并将这些函数返回的值分配给指针变量,则这种分配称为动态内存分配。内存在运行时关联。
静态内存分配:
动态内存分配:
静态内存分配和动态内存分配之间的区别
在程序开始执行之前(编译期间)分配内存。
在程序执行期间分配内存。
执行期间不执行任何内存分配或释放操作。
内存绑定在执行期间建立和销毁。
变量保持永久分配。
仅在程序单元处于活动状态时分配。
使用堆栈和堆实现。
使用数据段实现。
需要指针来访问变量。
不需要动态分配的指针。
比动态执行更快。
执行速度比静态执行速度慢。
需要更多的内存空间。
所需的内存空间更少。
静态内存分配是在编译期间在执行pf程序之前分配的内存。动态内存分配是在运行时程序执行期间分配的内存。