堆、栈、队列、各种变量(静态、动态、全局、局部)的区别和联系

2023-05-16

堆栈都是一种数据项按序排列的数据结构,只能在一端(称为栈顶(top))对数据项进行插入和删除。

堆 (heap)

堆(操作系统): 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收,分配方式类似于链表。

栈 (stack)

栈(操作系统):由操作系统(编译器)自动分配释放,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。

它是一种运算受限的线性表。其限制是仅允许在表的一端进行插入和删除运算。这一端被称为栈顶,相对地,把另一端称为栈底。

栈 是操作系统 在 建立某个进程时或者线程(在支持多线程的操作系统中是线程)为这个线程建立的存储区域,该区域具有FIFO的特性,在编译的时候可以指定需要的Stack的大小。
进程的栈是由多个栈帧构成的,其中每个栈帧都对应一个函数调用。当调用函数时,新的栈帧被压入栈;当函数返回时,相应的栈帧从栈中弹出。由于需要将函数返回地址这样的重要数据保存在程序员可见的堆栈中,因此也给系统安全带来了极大的隐患。
当程序写入超过缓冲区的边界时,就会产生所谓的**“缓冲区溢出”**。发生缓冲区溢出时,就会覆盖下一个相邻的内存块,导致程序发生一些不可预料的结果:也许程序可以继续,也许程序的执行出现奇怪现象,也许程序完全失败或者崩溃等。

堆栈区别:

  • 存储方式:

    • 栈使用的是一级缓存, 它们通常都是被调用时处于存储空间中,调用完毕立即释放
    • 堆则是存放在二级缓存中,生命周期由虚拟机的垃圾回收算法来决定(并不是一旦成为孤儿对象就能被回收)。所以调用这些对象的速度要相对来得低一些。
  • 存储内容:

    • 栈: 在函数调用时,第一个进栈的是主函数中函数调用后的下一条指令(函数调用语句的下一条可执行语句)的地址,然后是函数的各个参数,在大多数的C编译器中,参数是由右往左入栈的,然后是函数中的局部变量。**静态变量不入栈。**当本次函数调用结束后,局部变量先出栈,然后是参数,最后栈顶指针指向最开始存的地址,也就是主函数中的下一条指令,程序由该点继续运行。
    • 堆:一般是在堆的头部用一个字节存放堆的大小。堆中的具体内容有程序员安排。
  • 数据结构:

    • 堆(数据结构):堆可以被看成是一棵完全二叉树进出顺序随意如:堆排序。
    • 栈(数据结构):一种先进后出的数据结构。
  • 申请大小的限制:

    • 栈:在Windows下,栈是向低地址扩展的数据结构,是一块连续的内存的区域。这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的,在 WINDOWS下,栈的大小是2M(也有的说是1M,总之是一个编译时就确定的常数),如果申请的空间超过栈的剩余空间时,将提示overflow。因此,能从栈获得的空间较小。
    • 堆:堆是向高地址扩展的数据结构,是不连续的内存区域。这是由于系统是用链表来存储的空闲内存地址的,自然是不连续的,而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存。由此可见,堆获得的空间比较灵活,也比较大。
  • 分配和管理方式:

    • 栈由编译器自动管理,其分配方式有两种:静态分配和动态分配静态分配由编译器完成,比如局部变量的分配动态分配由alloca() 函数进行分配,但是栈的动态分配和堆是不同的,它的动态分配是由编译器进行释放,无需手动控制。
    • 堆是动态分配的,其空间的分配和释放都由程序员控制。也就是说,堆的大小并不固定,可动态扩张或缩减,其分配由malloc()等这类实时内存分配函数来实现。当进程调用malloc等函数分配内存时,新分配的内存就被动态添加到堆上(堆被扩张);当利用free等函数释放内存时,被释放的内存从堆中被剔除(堆被缩减)。

静态变量 (Stable Variable)

静态存储变量通常是在变量定义时就分定存储单元并一直保持不变,直至整个程序结束。静态变量,全局动态变量都是静态存储。
静态存储只初始化一次

作用域为当前文件,从定义/声明位置到文件结尾,生命周期为从程序运行到程序退出,即贯穿整个运行时间。

静态变量也可以用于存储常数。具体来说,静态变量(全局变量及汇编语言里定义的符号亦同)可用const,constant或final(根据语言决定)等关键字标识,这时其值就会在编译时设定,并且无法在运行时改变。

动态变量 (Dynamic Variable)

在程序执行过程中,使用它时才分配存储单元,使用完毕立即释放。

作用域为整个项目,即最终编译成可执行文件的所有文件中均可以使用动态全局变量,生命周期为从程序运行到程序退出,即贯穿整个运行时间。

动态全局变量可以通过extern关键字在外部文件中使用,但静态全局变量不可以在外部文件中使用。静态全局变量相当于限制了动态全局变量的作用域

全局变量 (Global Variable)

  1. 在所有函数的外部定义(包括主函数),定义之后的所有函数都能使用,属于静态存储
  2. 作用域为整个项目,即最终编译成可执行文件的所有文件中均可以使用动态全局变量。外部文件可以通过extern关键字来声明另一个文件中存在的全局变量
  3. 生命周期为从程序运行到程序退出,即贯穿整个运行时间
  4. 无显式初始化时默认初始化值为0

局部变量 (Local Variable)

  1. 在函数内部定义,属于动态存储,其他函数不能访问,外部文件也不能访问;
  2. 作用域为当前函数,从定义位置,到其所在的{}的结束位置
  3. 生命周期为从函数调用到函数退出
  4. 无显式初始化时默认初始化值为随机值
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

堆、栈、队列、各种变量(静态、动态、全局、局部)的区别和联系 的相关文章

随机推荐