最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C語言深入講解棧與堆和靜態(tài)存儲(chǔ)區(qū)的使用

 更新時(shí)間:2022年04月18日 11:14:33   作者:清風(fēng)自在 流水潺潺  
對(duì)大多數(shù)C 語言初學(xué)者來說,堆棧卻是一個(gè)很模糊的概念。堆棧是一種數(shù)據(jù)結(jié)構(gòu),一個(gè)在程序運(yùn)行時(shí)用于存放的地方,相信這可能是很多初學(xué)者共同的認(rèn)識(shí),靜態(tài)存儲(chǔ)區(qū)即內(nèi)存在程序編譯的時(shí)候就已經(jīng)分配好,這塊內(nèi)存在程序的整個(gè)運(yùn)行期間都存在

一、程序中的棧

  • 棧是現(xiàn)代計(jì)算機(jī)程序里最為重要的概念之一
  • 棧在程序中用于維護(hù)函數(shù)調(diào)用上下文
  • 函數(shù)中的參數(shù)和局部變量存儲(chǔ)在棧上

 棧保存了一個(gè)函數(shù)調(diào)用所需的維護(hù)信息

  • 參數(shù)
  • 返回地址
  • 局部變量
  • 調(diào)用上下文

二、函數(shù)的調(diào)用過程

每次函數(shù)調(diào)用都對(duì)應(yīng)著一個(gè)棧上的活動(dòng)記錄

  • 調(diào)用函數(shù)的活動(dòng)記錄位于棧的中部
  • 被調(diào)函數(shù)的活動(dòng)記錄位于棧的頂部

三、函數(shù)調(diào)用的棧變化

從main() 開始運(yùn)行

 main() 調(diào)用 f()

 當(dāng)從 f() 調(diào)用中返回 main()

四、函數(shù)調(diào)用棧上的數(shù)據(jù)

  • 函數(shù)調(diào)用時(shí),對(duì)應(yīng)的棧空間在函數(shù)返回前是專用的
  • 函數(shù)調(diào)用結(jié)束后,棧空間將被釋放,數(shù)據(jù)不再有效

        下面看一個(gè)指向棧數(shù)據(jù)的指針: 

#include <stdio.h>
 
int* g()
{
    int a[10] = {0};
    return a;
}
 
void f()
{
    int i = 0;
    int b[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    int *pointer = g();
    
    for (i = 0; i < 10; i++)
    {
        b[i] = pointer[i];
    }
    for(i = 0; i < 10; i++)
    {
        printf("%d\n", b[i]);
    } 
}
 
int main()
{
    f();
    return 0;
}

         輸出結(jié)果如下:

        如果把 

        for (i = 0; i < 10; i++)

       {

                b[i] = pointer[i];

       }

        注釋了,直接打印 pointer[i] 里面的數(shù)據(jù),如下:

#include <stdio.h>
 
int* g()
{
    int a[10] = {0};
    return a;
}
 
void f()
{
    int i = 0;
    int b[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    int *pointer = g();
    /*
    for (i = 0; i < 10; i++)
    {
        b[i] = pointer[i];
    }
    */
    for(i = 0; i < 10; i++)
    {
        printf("%d\n", pointer[i]);
    } 
}
 
int main()
{
    f();
    return 0;
}

        輸出結(jié)果如下:

         為什么直接打印 pointer[i] 里面的值會(huì)是這樣呢?因?yàn)?pointer 指向的空間是??臻g,??臻g在 g() 函數(shù)返回之后,活動(dòng)記錄就被釋放了。被釋放后調(diào)用 printf 函數(shù),printf 函數(shù)需要在棧上面建立一個(gè)活動(dòng)記錄。這個(gè)活動(dòng)記錄就會(huì)有 printf 函數(shù)的參數(shù)信息和返回值等,所以 pointer 所指向的內(nèi)存里面的數(shù)據(jù)由于 printf 函數(shù)的調(diào)用被改變了。因此,不能返回局部變量的地址,不能返回局部數(shù)組的數(shù)組名。

五、程序中的堆

  • 堆是程序中一塊預(yù)留的內(nèi)存空間,可由程序自由使用
  • 堆中被程序申請(qǐng)使用的內(nèi)存在被主動(dòng)釋放前將一直有效

        為什么有了棧還需要堆?

        答:棧上的數(shù)據(jù)在函數(shù)返回后就會(huì)被釋放掉,無法傳遞到函數(shù)外部,如:局部數(shù)組

C語言程序中通過庫函數(shù)的調(diào)用獲得堆空間

  • 頭文件:malloc.h
  • malloc -- 以字節(jié)的方式動(dòng)態(tài)申請(qǐng)堆空間
  • free -- 將堆空間歸還給系統(tǒng)

系統(tǒng)對(duì)堆空間的管理方式

空閑鏈表法,位圖法,對(duì)象池法等等

        以 int* p = (int*)malloc(sizeof(int)); 為例,要申請(qǐng) 4 個(gè)字節(jié)的大小,遍歷之后發(fā)現(xiàn)跟 5 Bytes 這個(gè)節(jié)點(diǎn)最接近,找到一個(gè)可以用的單元之后,就將這個(gè)單元的地址返還給了 p 指針。以前也提過使用 malloc 申請(qǐng)內(nèi)存空間時(shí)返回的內(nèi)存空間可能比申請(qǐng)的實(shí)際內(nèi)存空間要大一點(diǎn)點(diǎn),原因就是在空閑鏈表管理堆空間這樣的系統(tǒng)里面,它會(huì)找最近的那個(gè),找到后的一般都大于等于所需要的內(nèi)存空間,假如 5 Bytes 這個(gè)節(jié)點(diǎn)下所有的空閑內(nèi)存單元都用完的話,就會(huì)找 12 Bytes 節(jié)點(diǎn)下的內(nèi)存單元,這樣malloc 返回的內(nèi)存空間就有可能比自己實(shí)際申請(qǐng)的內(nèi)存空間要大。

六、程序中的靜態(tài)存儲(chǔ)區(qū)

  • 靜態(tài)存儲(chǔ)區(qū)隨著程序的運(yùn)行而分配空間
  • 靜態(tài)存儲(chǔ)區(qū)的生命周期直到程序運(yùn)行結(jié)束
  • 在程序的編譯期靜態(tài)存儲(chǔ)區(qū)的大小就已經(jīng)確定
  • 靜態(tài)存儲(chǔ)區(qū)主要用于保存全局變量和靜態(tài)局部變量
  • 靜態(tài)存儲(chǔ)區(qū)的信息最終會(huì)保存到可執(zhí)行程序中

        下面看一個(gè)靜態(tài)存儲(chǔ)區(qū)的驗(yàn)證代碼:

#include <stdio.h>
 
int g_v = 1;
 
static int g_vs  = 2;
 
void f()
{
    static int g_vl = 3;
    
    printf("%p\n", &g_vl);
}
 
int main()
{
    printf("%p\n", &g_v);
    
    printf("%p\n", &g_vs);
    
    f();
    
    return 0;
}

        輸出結(jié)果如下:

         可以看到這三個(gè)地址是順序存放的,因?yàn)檫@三個(gè)變量都是存放在程序的靜態(tài)存儲(chǔ)區(qū),靜態(tài)存儲(chǔ)區(qū)在程序里面有固定的起始地址。 

七、小結(jié)

棧,堆和靜態(tài)存儲(chǔ)區(qū)是程序中的三個(gè)基本數(shù)據(jù)區(qū)

  • 棧區(qū)主要用于函數(shù)調(diào)用的使用
  • 堆區(qū)主要是用于內(nèi)存的動(dòng)態(tài)申請(qǐng)和歸還
  • 靜態(tài)存儲(chǔ)區(qū)用于保存全局變量和靜態(tài)變量

到此這篇關(guān)于C語言深入講解棧與堆和靜態(tài)存儲(chǔ)區(qū)的使用的文章就介紹到這了,更多相關(guān)C語言 棧與堆內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C++實(shí)現(xiàn)簡單插件機(jī)制原理解析

    C++實(shí)現(xiàn)簡單插件機(jī)制原理解析

    這篇文章主要介紹了C++實(shí)現(xiàn)簡單插件機(jī)制原理解析,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-02-02
  • C++內(nèi)存模型與名稱空間概念講解

    C++內(nèi)存模型與名稱空間概念講解

    這篇文章主要介紹了C++內(nèi)存模型與名稱空間,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧
    2023-01-01
  • 淺談C++ Explicit Constructors(顯式構(gòu)造函數(shù))

    淺談C++ Explicit Constructors(顯式構(gòu)造函數(shù))

    下面小編就為大家?guī)硪黄獪\談C++ Explicit Constructors(顯式構(gòu)造函數(shù))。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2016-12-12
  • 解讀構(gòu)造函數(shù)的調(diào)用規(guī)則、深拷貝與淺拷貝

    解讀構(gòu)造函數(shù)的調(diào)用規(guī)則、深拷貝與淺拷貝

    本文主要介紹了C++中的默認(rèn)構(gòu)造函數(shù)、拷貝構(gòu)造函數(shù)以及深拷貝和淺拷貝的概念,并通過實(shí)際代碼示例進(jìn)行了詳細(xì)講解
    2024-11-11
  • 一文讀懂c++11 Lambda表達(dá)式

    一文讀懂c++11 Lambda表達(dá)式

    這篇文章主要介紹了c++11 Lambda表達(dá)式的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)C++,感興趣的朋友可以了解下
    2020-08-08
  • C++ OpenCV實(shí)戰(zhàn)之網(wǎng)孔檢測的實(shí)現(xiàn)

    C++ OpenCV實(shí)戰(zhàn)之網(wǎng)孔檢測的實(shí)現(xiàn)

    這篇文章主要介紹了如何利用C++和OpenCV實(shí)現(xiàn)網(wǎng)孔檢測,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)OpenCV有一定幫助,感興趣的小伙伴可以了解一下
    2022-05-05
  • CentOS下Jsoncpp安裝配置的方法

    CentOS下Jsoncpp安裝配置的方法

    本文主要介紹了CentOS下Jsoncpp安裝配置的方法,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • 詳解C語言中的預(yù)處理命令

    詳解C語言中的預(yù)處理命令

    初學(xué)C語言的時(shí)候,我們會(huì)在開頭寫下一句話,#include<stdio.h>,這就是預(yù)處理命令,下面我們通過這篇文章來了解一下,感興趣的可以跟隨小編一起學(xué)習(xí)一下
    2022-12-12
  • C語言中求字符串長度的函數(shù)的幾種實(shí)現(xiàn)方法

    C語言中求字符串長度的函數(shù)的幾種實(shí)現(xiàn)方法

    這篇文章主要介紹了C語言中求字符串長度的函數(shù)的幾種實(shí)現(xiàn)方法,需要的朋友可以參考下
    2018-08-08
  • C++簡單實(shí)現(xiàn)Dijkstra算法

    C++簡單實(shí)現(xiàn)Dijkstra算法

    這篇文章主要為大家詳細(xì)介紹了C++簡單實(shí)現(xiàn)Dijkstra算法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-05-05

最新評(píng)論

庄河市| 阜南县| 靖安县| 平罗县| 湖南省| 清河县| 宜兰市| 镇江市| 辉南县| 五台县| 乐陵市| 恩施市| 忻城县| 威海市| 万年县| 康保县| 齐齐哈尔市| 曲阳县| 禄劝| 阿城市| 讷河市| 拉孜县| 白朗县| 封开县| 杭锦旗| 清水县| 富源县| 西平县| 加查县| 大同县| 温宿县| 自治县| 泊头市| 庆阳市| 临颍县| 绥滨县| 板桥市| 朝阳市| 华亭县| 佛坪县| 且末县|