久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

C語言程序里全局變量,、局部變量,、堆、棧的存儲區(qū)域

 喜歡站在山上 2020-12-14

一、存儲區(qū)域介紹

  • C語言在內(nèi)存中一共分為如下幾個區(qū)域

區(qū)域作用
內(nèi)存棧區(qū)存放局部變量名
內(nèi)存堆區(qū)存放new或者malloc出來的對象
常數(shù)區(qū)存放局部變量或者全局變量的值
靜態(tài)區(qū)用于存放全局變量或者靜態(tài)變量
代碼區(qū)二進(jìn)制代碼
  • 區(qū)域的解釋

棧區(qū)(stack)–由編譯器自動分配釋放 ,,存放函數(shù)的參數(shù)值,,局部變量的值等。其操作方式類似于數(shù)據(jù)結(jié)構(gòu)中的棧,。

堆區(qū)(heap)–般由程序員分配釋放,, 若程序員不釋放,程序結(jié)束時可能由OS回收 ,。注意它與數(shù)據(jù)結(jié)構(gòu)中的堆是兩回事,,分配方式類似于鏈表。

全局區(qū)(靜態(tài)區(qū))(static)–全局變量和靜態(tài)變量的存儲是放在一塊的,,初始化的全局變量和靜態(tài)變量在一塊區(qū)域(RW),,未初始化的全局變量和未初始化的靜態(tài)變量在相鄰的另一塊區(qū)域(ZI)。程序結(jié)束后有系統(tǒng)釋放,。 和“?!币粯?,通常是用于那些在編譯期間就能確定存儲大小的變量的存儲區(qū),但它用于的是在整個程序運(yùn)行期間都可見的全局變量和靜態(tài)變量,。

文字常量區(qū)–常量字符串就是放在這里的,。程序結(jié)束后由系統(tǒng)釋放 (RO)

程序代碼區(qū)–存放函數(shù)體的二進(jìn)制代碼。 (RO)

常量存儲區(qū)—和“全局/靜態(tài)存儲區(qū)”一樣,,通常是用于那些在編譯期間就能確定存儲大小的常量的存儲區(qū),并且在程序運(yùn)行期間,,存儲區(qū)內(nèi)的常量是全局可見的,。這是一塊比較特殊的存儲去,他們里面存放的是常量,,不允許被修改,。

  • 內(nèi)存存在兩種屬性:靜態(tài)分配內(nèi)存和動態(tài)分配內(nèi)存。

靜態(tài)分配內(nèi)存:是在程序編譯和鏈接時就確定好的內(nèi)存,。
動態(tài)分配內(nèi)存:是在程序加載,、調(diào)入、執(zhí)行的時候分配/回收的內(nèi)存,。

  • 堆棧

堆和棧都是動態(tài)分配內(nèi)存,,兩者空間大小都是可變的。

Stack: 棧,,存放Automatic Variables,,按內(nèi)存地址由高到低方向生長,其最大大小由編譯時確定,,速度快,,但自由性差,最大空間不大,。

通常是用于那些在編譯期間就能確定存儲大小的變量的存儲區(qū),,用于在函數(shù)作用域內(nèi)創(chuàng)建,在離開作用域后自動銷毀的變量的存儲區(qū),。通常是局部變量,,函數(shù)參數(shù)等的存儲區(qū)。他的存儲空間是連續(xù)的,,兩個緊密挨著定義的局部變量,,他們的存儲空間也是緊挨著的。棧的大小是有限的,,通常Visual C++編譯器的默認(rèn)棧的大小為1MB,,所以不要定義int a[1000000]這樣的超大數(shù)組。

Heap: 堆,,自由申請的空間,,按內(nèi)存地址由低到高方向生長,,其大小由系統(tǒng)內(nèi)存/虛擬內(nèi)存上限決定,速度較慢,,但自由性大,,可用空間大。
通常是用于那些在編譯期間不能確定存儲大小的變量的存儲區(qū),,它的存儲空間是不連續(xù)的,一般由malloc(或new)函數(shù)來分配內(nèi)存塊,,并且需要用free(delete)函數(shù)釋放內(nèi)存,。如果程序員沒有釋放掉,那么就會出現(xiàn)常說的內(nèi)存泄漏問題,。需要注意的是,,兩個緊挨著定義的指針變量,,所指向的malloc出來的兩塊內(nèi)存并不一定的是緊挨著的,,所以會產(chǎn)生內(nèi)存碎片。另外需要注意的一點是,,堆的大小幾乎不受限制,,理論上每個程序最大可達(dá)4GB。
每個線程都會有自己的棧,,但是堆空間是共用的。

  • Text & Data & Bss

.text: 也稱為代碼段(Code),用來存放程序執(zhí)行代碼,,同時也可能會包含一些常量(如一些字符串常量等),。該段內(nèi)存為靜態(tài)分配,只讀(某些架構(gòu)可能允許修改),。 這塊內(nèi)存是共享的,當(dāng)有多個相同進(jìn)程(Process)存在時,共用同一個text段,。

.data: 也有的地方叫GVAR(global value),,用來存放程序中已經(jīng)初始化的非零全局變量。靜態(tài)分配,。 data又可分為讀寫(RW)區(qū)域和只讀(RO)區(qū)域,。
-> RO段保存常量所以也被稱為.constdata
-> RW段則是普通非常全局變量,靜態(tài)變量就在其中 .bss: 存放程序中為初始化的和零值全局變量,。靜態(tài)分配,在程序開始時通常會被清零。

  • 從低地址到高地址
    在這里插入圖片描述

二,、在ubuntu系統(tǒng)中輸出信息進(jìn)行驗證

  • 輸入代碼main.c

#include <stdio.h>#include <string.h>#include <stdlib.h> void before(){ } char g_buf[16];char g_buf2[16];char g_buf3[16];char g_buf4[16];char g_i_buf[]='123';char g_i_buf2[]='123';char g_i_buf3[]='123'; void after(){ } int main(int argc, char **argv){ char l_buf[16]; char l_buf2[16]; char l_buf3[16]; static char s_buf[16]; static char s_buf2[16]; static char s_buf3[16]; char *p_buf; char *p_buf2; char *p_buf3; p_buf = (char *)malloc(sizeof(char) * 16); p_buf2 = (char *)malloc(sizeof(char) * 16); p_buf3 = (char *)malloc(sizeof(char) * 16); printf('g_buf: 0x%x\n', g_buf); printf('g_buf2: 0x%x\n', g_buf2); printf('g_buf3: 0x%x\n', g_buf3); printf('g_buf4: 0x%x\n', g_buf4); printf('g_i_buf: 0x%x\n', g_i_buf); printf('g_i_buf2: 0x%x\n', g_i_buf2); printf('g_i_buf3: 0x%x\n', g_i_buf3); printf('l_buf: 0x%x\n', l_buf); printf('l_buf2: 0x%x\n', l_buf2); printf('l_buf3: 0x%x\n', l_buf3); printf('s_buf: 0x%x\n', s_buf); printf('s_buf2: 0x%x\n', s_buf2); printf('s_buf3: 0x%x\n', s_buf3); printf('p_buf: 0x%x\n', p_buf); printf('p_buf2: 0x%x\n', p_buf2); printf('p_buf3: 0x%x\n', p_buf3); printf('before: 0x%x\n', before); printf('after: 0x%x\n', after); printf('main: 0x%x\n', main); if (argc > 1) { strcpy(l_buf, argv[1]); } return 0;}
  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

  • 11

  • 12

  • 13

  • 14

  • 15

  • 16

  • 17

  • 18

  • 19

  • 20

  • 21

  • 22

  • 23

  • 24

  • 25

  • 26

  • 27

  • 28

  • 29

  • 30

  • 31

  • 32

  • 33

  • 34

  • 35

  • 36

  • 37

  • 38

  • 39

  • 40

  • 41

  • 42

  • 43

  • 44

  • 45

  • 46

  • 47

  • 48

  • 49

  • 50

  • 51

  • 52

  • 53

  • 54

  • 55

  • 56

  • 57

  • 58

  • 59

  • 60

  • 61

  • 62

  • 63

  • 64

  • 65

  • 66

  • 67

  • 68

  • 69

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

  • 11

  • 12

  • 13

  • 14

  • 15

  • 16

  • 17

  • 18

  • 19

  • 20

  • 21

  • 22

  • 23

  • 24

  • 25

  • 26

  • 27

  • 28

  • 29

  • 30

  • 31

  • 32

  • 33

  • 34

  • 35

  • 36

  • 37

  • 38

  • 39

  • 40

  • 41

  • 42

  • 43

  • 44

  • 45

  • 46

  • 47

  • 48

  • 49

  • 50

  • 51

  • 52

  • 53

  • 54

  • 55

  • 56

  • 57

  • 58

  • 59

  • 60

  • 61

  • 62

  • 63

  • 64

  • 65

  • 66

  • 67

  • 68

  • 69

l_buf/l_buf2/l_buf3 ,,直接定義,,是由編譯器自動分配的,,存儲在棧中
s_buf/s_buf2/s_buf3,,定義static,編譯器編譯時分配內(nèi)存,。為全局變量,,在全局初始化區(qū)
p_buf/p_buf2/p_buf3,,他們指向的空間,通過malloc申請空間,存放在堆中
g_buf/g_buf2/g_buf3/g_buf4/,定義的為全局變量,,在全局初始化區(qū)

  • 運(yùn)行結(jié)果
    在這里插入圖片描述

  • 分析結(jié)果
    棧存放區(qū)域是由高地址到低地址向下增長
    堆存放區(qū)是由低地址到高地址像上增長
    靜態(tài)變量地址從高地址到低地址向下增長
    函數(shù)地址是從低地址到高地址向上增長

三,、在Keil中針對stm32系統(tǒng)進(jìn)行驗證

  • 總結(jié)

內(nèi)存高地址棧區(qū)

堆區(qū)

.bss段

.data段

常量區(qū)
內(nèi)存低地址代碼區(qū)
  • 在MDK中編譯后可以看到Code,、RO-data、RW-data,、ZI-data的大小

Code是存儲程序代碼的,;
RO-data是存儲const常量和指令
RW-data是存儲初始化值不為0的全局變量
ZI-data是存儲未初始化的全局變量或初始化值為0的全局變量

在這里插入圖片描述

  • keil中的代碼

#include 'delay.h'#include 'usart.h'#include 'string.h'#include <stdio.h>#include <stdlib.h>int k1 = 1;int k2;static int k3 = 2;static int k4;int main(void) {delay_init();     //延時函數(shù)初始化NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);// 設(shè)置中斷優(yōu)先級分組2uart_init(115200); //串口初始化為115200  while(1){    static int m1=2, m2;    int i = 1;    char *p;    char str[10] = 'hello';    char *var1 = '123456';    char *var2 = 'abcdef';    int *p1=malloc(4);    int *p2=malloc(4);    free(p1);    free(p2);    printf('棧區(qū)-變量地址');printf('   i:%p\r\n', &i);printf('                p:%p\r\n', &p);printf('              str:%p\r\n', str);    printf('堆區(qū)-動態(tài)申請地址');    printf('  %p\r\n', p1);    printf('                   %p\r\n', p2);    printf('\r\n.bss段\r\n');printf('全局外部無初值 k2:%p\r\n', &k2);printf('靜態(tài)外部無初值 k4:%p\r\n', &k4);printf('靜態(tài)內(nèi)部無初值 m2:%p\r\n', &m2);    printf('\r\n.data段\r\n');    printf('全局外部有初值 k1:%p\r\n', &k1);    printf('靜態(tài)外部有初值 k3:%p\r\n', &k3);    printf('靜態(tài)內(nèi)部有初值 m1:%p\r\n', &m1);    printf('\r\n常量區(qū)\r\n');    printf('文字常量地址     :%p\r\n',var1);    printf('文字常量地址     :%p\r\n',var2);    printf('\r\n代碼區(qū)\r\n');    printf('程序區(qū)地址       :%p\r\n',&main);}}12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849501234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950
  • 串口調(diào)試結(jié)果
    在這里插入圖片描述 

  • 分析結(jié)果可知,stm32的棧區(qū)的地址值是從上到下減小的,,堆區(qū)則是從上到下增長的,。

四、總結(jié)

通過這次學(xué)習(xí)讓我對C程序的內(nèi)存分配有進(jìn)一步的認(rèn)識,,知道一個C程序內(nèi)存包括的部分,,了解了棧和堆地址變化的不同。而且在不同系統(tǒng)中,區(qū)域內(nèi)的地址值變化不一定是相同的,。

五,、參考資料

1、https://blog.csdn.net/feier7501/article/details/8564300
2,、https://blog.csdn.net/jirryzhang/article/details/79518408
3,、https://blog.csdn.net/qq_43279579/article/details/110308101

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點,。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請點擊一鍵舉報,。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多