内容简介:中文原文:英文原文:校对:
栈和堆的区别
中文原文: 栈和堆的区别
英文原文: Memory:Stack vs Heap
校对: xiaobai22
目录
- 栈和堆的区别
- 栈
- 堆
-
栈和堆的优缺点
- 栈
- 堆
- 例子
- 什么时候使用堆
- 关联文章
栈和堆的区别
到目前为止,我们已经知道如何声明基础变量类型,例如: int
, double
等以及复杂类型例如:数组和结构体。在 C语言 中,我们使用和其他语言诸如MATLAB,Python相同的语法声明它们,并把这些变量推到栈里。
栈
什么是栈?这是计算机内存的特定区域,它存储每个函数创建的临时变量(包括 main()
函数)。栈使用“LIFO”数据结构,由CPU管理和优化。每当函数声明一个新变量,它就会被推入栈。当函数退出时,所有被该函数推入栈的变量会被释放(这代表,它们已经被删除)。一旦栈的变量释放,此内存区可以被其他栈变量使用。
使用栈保存变量的优点:CPU帮你管理内存。你不需要手动分配和释放。更重要的是,CPU可以高效的组织内存,读写栈变量会非常快。
理解栈的关键 : 当函数退出时 ,它推入栈的所有变量会被弹出(永远丢失)。栈变量本质是局部的。这涉及到我们之前了解的 变量作用域 或 局部和全局变量。在C语言编程通常会遇到此类BUG:从函数外部企图读取函数内部的变量(在函数退出之后)。
栈另一个需要注意的特征是:保存在栈的变量是有大小限制的。堆的情况却不一样。
栈的总结:
- 栈的增长和缩容发生在函数推入和弹出局部变量时
- 不需要你自己管理内存,变量会自动分配和释放
- 栈有大小限制
- 栈变量仅存在于创建它们的函数运行的时候
堆
堆是计算机的内存区,它不会帮你自动管理,也不由CPU管理。堆有更大的空间。你需要使用 C语言内置函数 malloc()
和 calloc()
分配内存到堆。当不再使用这块内存时,你负责使用 free()
进行释放。如果没做这步,你的程序会发生内存泄露。堆上的内存仍然被占用(不能被其他进程使用)。正如我们在调试中看到的,用 valgrind
工具,帮助检测内存泄漏。
和栈不一样,堆没有大小限制(除了物理内存限制)。堆的读写稍微比较慢,因为必须使用指针访问堆上的内存。我们在后面会讨论指针。
和栈不一样,其他函数和你程序上的任何地方都可以访问堆上创建的变量。堆本质是全局的。
栈和堆的优缺点
栈
- 访问非常快
- 不必显式的分配变量
- CPU有效的管理,不会产生内存碎片
- 仅用于局部变量
- 有大小限制(不同操作系统有区别)
- 大小不能被调整
堆
realloc()
例子
这是一个简短的程序,创建变量到栈。
#include double multiplyByTwo (double input) { double twice = input * 2.0; return twice; } int main (int argc, char *argv[]) { int age = 30; double salary = 12345.67; double myList[3] = {1.2, 2.3, 3.4}; printf("double your salary is %.3f\n", multiplyByTwo(salary)); return 0; }
double your salary is 24691.340
在10,11,12行我们声明了变量:int ,double,长度为3的浮点型数组。 main()
进行分配的时候,这3个变量被推到栈。当 main()
函数退出(程序停止),这些变量会被弹出栈。同样的,在函数 multiplyByTwo()
有2个 double
型的变量,会被推到栈。 multiplyByTwo()
退出,这2个变量会被弹出栈,永远消失。
顺便提一句,有一种方法可以告诉C语言,即使创建函数退出后,仍然可以保留栈变量,就是在声明变量时使用 static
关键字。因此,使用 static
关键字声明的变量类似于全局变量,但只能在创建它的函数中可见。这是一种奇怪的结构,除非在非常特殊的情况下,否则你可能不需要它
这是另一个版本,分配所有变量到堆而不是栈:
#include #include double *multiplyByTwo (double *input) { double *twice = malloc(sizeof(double)); *twice = *input * 2.0; return twice; } int main (int argc, char *argv[]) { int *age = malloc(sizeof(int)); *age = 30; double *salary = malloc(sizeof(double)); *salary = 12345.67; double *myList = malloc(3 * sizeof(double)); myList[0] = 1.2; myList[1] = 2.3; myList[2] = 3.4; double *twiceSalary = multiplyByTwo(salary); printf("double your salary is %.3f\n", *twiceSalary); free(age); free(salary); free(myList); free(twiceSalary); return 0; }
正如你所看到的,使用 malloc()
分配内存到堆和使用 free()
释放,这不是大问题,但有点麻烦。另外一个需要注意的是到处都是星符号。它们是什么?答案是,它们是指针。 malloc()
处理指针,而不是真实的值。我们后面会更详细讨论指针。指针在C语言是一种特殊的数据类型,它保存地址在内存而不是真实的值。因此在上面第5行,2个变量都不是 double
, 但它们是指向浮点型的指针。变量double 保存了一个地址在内存。
什么时候使用堆
什么时候使用堆?什么时候使用栈?如果你要分配一块大内存和你需要保留这个变变量很长时间,那么你就要分配它们到堆。如果你处理的是相对小的变量,只需要存活在函数使用期间,那么你可以使用栈,它更容易更快。如果你需要可以动态改变大小的变量例如:数据和结构体,那你需要分配它们到堆,用动态内存分配函数 mallco() calloc() realloc()
和 free()
手动管理内存。我们会讨论动态分配数据结构在讨论完指针后。
以上所述就是小编给大家介绍的《[译]栈和堆的区别》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。