[译]栈和堆的区别

栈和堆的区别

中文原文:栈和堆的区别
英文原文:Memory:Stack vs Heaphtml

校对:xiaobai22git

目录github

  • 栈和堆的区别
  • 栈和堆的优缺点编程

  • 例子
  • 何时使用堆
  • 关联文章

栈和堆的区别

到目前为止,咱们已经知道如何声明基础变量类型,例如: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()手动管理内存。咱们会讨论动态分配数据结构在讨论完指针后。

相关连接

The Stack and the Heap

What and Where are the stack and heap

相关文章
相关标签/搜索