zoukankan      html  css  js  c++  java
  • C内存管理一 概述

    我们写了这么多年的程序猿。可能理论方面还比不上大学生。有人 "嘘"我了,假设有能回答下面几个问题的同学请举手:
    1.面试常常遇到:同学请说说堆栈的差别?
    2.同学请说说一个函数在堆栈中调用过程(首先要知道函数过程是保存在什么中的)。
    3.静态变量、全局变量、局部变量、常量等哪些是保存在堆中,哪些是栈中。哪些是静态区域中。
    事实上回答第一个我问题,第二和第三问题就是........还真有人举手。就算你举手了,我也要讲。有不正确的地方。这几位同学给我批评指正。

    先来看图:



    就上图来看堆栈差别是.......非常明显堆比栈大。(别嘘),操作系统太高深此处省略,其他还有文字常量区、程序代码区。在其他我也不知道有什么此处省略。

    我们专门来看看 栈、堆、静态存储区。准备好了吗?

    什么是堆,什么是栈

    堆--heap  栈--stack  最大的差别:一个四个字母。一个5个字母。

    宏观上来说。栈是由系统提供的数据结果,而堆是由C/C++函数库提供的。

    从这句话中我的推測理解是栈是系统提供和管理的,而堆是编程语言提供和管理的。在浓缩一下就是栈是自己主动管理的。而堆是手动管理的。

    微观上来说。

    堆栈就是一种方式,一种存储数据的方式或者一种数据结构。

    看它的定义:栈是一种先进后出的线性表,仅仅要符合先进后出的原则的线性表都是栈。

    而堆是一种二叉树,有最大推、最小堆,我们经常使用的什么冒泡、选择等能够用于堆排序。

    总之浓缩一下:

    栈是系统自己主动管理、採用先进后出方式存储数据的存储区域。

    而堆是採用手动管理(malloc 和 free程序中创建、释放)、採用二叉树存储数据的存储区域。(特殊情况除外。比方栈也有动态分配和静态分配)

    栈是一种先进后出的线性表,仅仅要符合先进后出的原则的线性表都是栈。

    综上:栈的特点就是高速、高效、可是因为是机器读写,灵活性相对较弱。堆因为能够手动大小分配,较为灵活、使用面广泛,可是速度没有栈快。


    堆栈差别

    1、分配方式:自己主动、手动
    2、速度、大小、响应速度:栈快、小,堆慢、大
    3、数据存储方式:先进后出、二叉树

    补充说明:静态存储区似乎给忘了,仅仅要记住一点静态存储区是用来存放全局变量和静态变量的。


    程序中哪些是放在堆中、哪些是放到栈中

    1、栈区(stack): 由编译器自己主动分配释放 。存放函数的參数值。局部变量的值等。其操作方式类似于数据结构中的栈。 
     比如,声明在函数中一个局部变量 int b; 系统自己主动在栈中为b开辟空间比如:声明在函数中一个局部变量 int b; 系统自己主动在栈中为b开辟空间
    2、堆区(heap): 一般由程序猿分配释放, 若程序猿不释放,程序结束时可能由OS回收 。
    须要程序猿自己申请。并指明大小,在c中malloc函数 如p1 = (char *)malloc(10); 在C++中用new运算符 如p2 = (char *)malloc(10); 可是注意p1、p2本身是在栈中的。比如:在c中malloc函数 
    p1 = (char *)malloc(10); 
    p1 = (char *)malloc(20); 
    可是注意p1,p2本身是在栈中的。
    到此我的推測----栈中存储的大部分是地址(还有写少许的局部变量值)。
    3、全局区(静态区)(static):全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域。 未初始化的全局变量和未初始化的静态变量在相邻的还有一块区域。 (程序结束后有系统释放 ,即生命周期)
    4、文字常量区 —常量字符串就是放在这里的。
    5、程序代码区—存放函数体的二进制代码。

    程序说明:

    int a = 0; //全局初始化区 
    char *p1; //全局未初始化区 
    main() 
    { 
      int b; //栈 
      char s[] = "abc"; //栈 
      char *p2; //栈 
      char *p3 = "123456"; //123456在常量区,p3在栈上。 
      static int c =0; //全局(静态)初始化区 
      p1 = (char *)malloc(10); 
      p2 = (char *)malloc(20); 
      //分配得来得10和20字节的区域就在堆区。 
      strcpy(p1, "123456"); //123456放在常量区,编译器可能会将它与p3所指向的"123456"优化成一个地方。 
    } 

    函数调用过程

    函数调用主要是在栈中进行的:在函数调用时,第一个进栈的是主函数中后的下一条指令(函数调用语句的下一条可执行语句)的地址。然后是函数的各个參数,在大多数的C编译器中。參数是由右往左入栈的,然后是函数中的局部变量。注意静态变量是不入栈的。

    当本次函数调用结束后,局部变量先出栈。然后是參数。最后栈顶指针指向最開始存的地址。也就是主函数中的下一条指令,程序由该点继续执行。



  • 相关阅读:
    (Good Bye 2019) Codeforces 1270B Interesting Subarray
    (Good Bye 2019) Codeforces 1270A Card Game
    Codeforces 1283D Christmas Trees(BFS)
    Codeforces 1283C Friends and Gifts
    Codeforces 1283B Candies Division
    1095 Cars on Campus (30)
    1080 Graduate Admission (30)
    1099 Build A Binary Search Tree (30)
    1018 Public Bike Management (30)
    1087 All Roads Lead to Rome (30)
  • 原文地址:https://www.cnblogs.com/yangykaifa/p/7025889.html
Copyright © 2011-2022 走看看