免费国产午夜视频在线_日韩一区二区三区91_日本高清视频在线网站_无码αⅴ视频在线观看_亚洲永久免费播放片app一_国产爆乳呻吟在线观看_欧洲 日韩 国产 精品_久久w免费人成看片中文_色婷婷日日躁夜夜躁_亚洲国产网红无码播放

  • 相關(guān)文章
    軟件資訊
    當(dāng)前位置:啟肯科技> 新聞資訊> 軟件資訊> 詳情頁

    C語言編程程序的內(nèi)存如何布局

    TAG: C語言(1) 編程程序(1) 時間:2017-08-28 瀏覽:0

    重點關(guān)注以下內(nèi)容:

      C語言程序在內(nèi)存中各個段的組成

      C語言程序連接過程中的特性和常見錯誤

      C語言程序的運行方式

      一:C語言程序的存儲區(qū)域

      由C語言代碼(文本文件)形成可執(zhí)行程序(二進制文件),需要經(jīng)過編譯-匯編-連接三個階段。編譯過程把C語言文本文件生成匯編程序,匯編過程把匯編程序形成二進制機器代碼,連接過程則將各個源文件生成的二進制機器代碼文件組合成一個文件。

      C語言編寫的程序經(jīng)過編譯-連接后,將形成一個統(tǒng)一文件,它由幾個部分組成。在程序運行時又會產(chǎn)生其他幾個部分,各個部分代表了不同的存儲區(qū)域:

      1.代碼段(Code或Text)

      代碼段由程序中執(zhí)行的機器代碼組成。在C語言中,程序語句進行編譯后,形成機器代碼。在執(zhí)行程序的過程中,CPU的程序計數(shù)器指向代碼段的每一條機器代碼,并由處理器依次運行。

      2.只讀數(shù)據(jù)段(RO data)

      只讀數(shù)據(jù)段是程序使用的一些不會被更改的數(shù)據(jù),使用這些數(shù)據(jù)的方式類似查表式的操作,由于這些變量不需要更改,因此只需要放置在只讀存儲器中即可。

      3.已初始化讀寫數(shù)據(jù)段(RW data)

      已初始化數(shù)據(jù)是在程序中聲明,并且具有初值的變量,這些變量需要占用存儲器的空間,在程序執(zhí)行時它們需要位于可讀寫的內(nèi)存區(qū)域內(nèi),并具有初值,以供程序運行時讀寫。

      4.未初始化數(shù)據(jù)段(BSS)

      未初始化數(shù)據(jù)是在程序中聲明,但是沒有初始化的變量,這些變量在程序運行之前不需要占用存儲器的空間。

      5.堆(heap)

      堆內(nèi)存只在程序運行時出現(xiàn),一般由程序員分配和釋放。在具有操作系統(tǒng)的情況下,如果程序沒有釋放,操作系統(tǒng)可能在程序(例如一個進程)結(jié)束后回收內(nèi)存。

      6.棧(stack)

      棧內(nèi)存只在程序運行時出現(xiàn),在函數(shù)內(nèi)部使用的變量、函數(shù)的參數(shù)以及返回值將使用?臻g,?臻g由編譯器自動分配和釋放。

      C語言目標(biāo)文件的內(nèi)存布局

      看一個例子:

      int a = 0; //全局初始化區(qū),。data段

      static int b=20; //全局初始化區(qū),。data段

      char *p1; //全局未初始化區(qū) .bss段

      const int A = 10; //.rodata段

      void main(void)

      {

      int b; //棧

      char s[] = "abc"; //棧

      char *p2; //棧

      static int c = 0; //全局(靜態(tài))初始化區(qū) .data段

      char *p3 = "123456"; //123456\0在常量區(qū),p3 在棧上。

      p1 = (char*) malloc(10);//分配得來的10和20個字節(jié)的區(qū)域就在堆區(qū)

      p2 = (char*) malloc(20);

      strcpy(p1, "123456"); //123456\0 在常量區(qū),編譯器可能會將它與p3所指向的"123456"優(yōu)化成一個地方

      }

      代碼段、只讀數(shù)據(jù)段、讀寫數(shù)據(jù)段、未初始化數(shù)據(jù)段屬于靜態(tài)區(qū)域,而堆和棧屬于動態(tài)區(qū)域。代碼段、只讀數(shù)據(jù)段和讀寫數(shù)據(jù)段將在鏈接之后產(chǎn)生,未初始化數(shù)據(jù)段將在程序初始化的時候開辟,而堆和棧將在程序的運行中分配和釋放。C語言程序分為映像和運行時兩種狀態(tài)。在編譯-連接后形成的映像中,將只包含代碼段(Text)、只讀數(shù)據(jù)段(RO Data)和讀寫數(shù)據(jù)段(RW Data)。在程序運行之前,將動態(tài)生成未初始化數(shù)據(jù)段(BSS),在程序的運行時還將動態(tài)形成堆(Heap)區(qū)域和棧(Stack)區(qū)域。一般來說,在靜態(tài)的映像文件中,各個部分稱之為節(jié)(Section),而在運行時的各個部分稱之為段(Segment)。如果不詳細區(qū)分,可以統(tǒng)稱為段。

      知識點:

      C語言在編譯和連接后,將生成代碼段(Text)、只讀數(shù)據(jù)段(RO Data)和讀寫數(shù)據(jù)段(RW Data)。在運行時,除了以上三個區(qū)域外,還包括未初始化數(shù)據(jù)段(BSS)區(qū)域和堆(Heap)區(qū)域和棧(Stack)區(qū)域。

      二:C語言程序的段

      1.代碼段(code或text)

      代碼段由各個函數(shù)產(chǎn)生,函數(shù)的每一個語句將最終經(jīng)過編繹和匯編生成二進制機器代碼(具體生生哪種體系結(jié)構(gòu)的機器代碼由編譯器決定)。

      2.只讀數(shù)據(jù)段(RO Data)

      只讀數(shù)據(jù)段由程序中所使用的數(shù)據(jù)產(chǎn)生,該部分數(shù)據(jù)的特點是在運行中不需要改變,因此編譯器會將該數(shù)據(jù)段放入只讀的部分中。C語言中的只讀全局變量,只讀局部變量,程序中使用的常量等會在編譯時被放入到只讀數(shù)據(jù)區(qū)。

      注意:定義全局變量const char a[100]={"ABCDEFG"};將生成大小為100個字節(jié)的只讀數(shù)據(jù)區(qū),并使用“ABCDEFG”初始化。如果定義為:const char a[ ]={"ABCDEFG"};則根據(jù)字符串長度生成8個字節(jié)的只讀數(shù)據(jù)段(還有’\0’),所以在只讀數(shù)據(jù)段中,一般都需要做完全的初始化。

      3.讀寫數(shù)據(jù)段(RW Data)

      讀寫數(shù)據(jù)段表示了在目標(biāo)文件中一部分可以讀也可以寫的數(shù)據(jù)區(qū),在某些場合它們又被稱為已初始化數(shù)據(jù)段,這部分數(shù)據(jù)段和代碼段,與只讀數(shù)據(jù)段一樣都屬于程序中的靜態(tài)區(qū)域,但具有可寫性的特點。通常已初始化的全局變量和局部靜態(tài)變量被放在了讀寫數(shù)據(jù)段,如: 在函數(shù)中定義static char b[ 100]={“ABCDEFG”};讀寫數(shù)據(jù)區(qū)的特點是必須在程序經(jīng)過初始化,如果只定義,沒初始值,則不會生成讀寫數(shù)據(jù)區(qū),而會定位為未初始化數(shù)據(jù)區(qū)(BSS)。如果全局變量(函數(shù)外部定義的變量)加入static修飾,這表示只能在文件內(nèi)使用,而不能被其他文件使用。

      4. 未初始化數(shù)據(jù)段(BSS)

      與讀寫數(shù)據(jù)段類似,它也屬于靜態(tài)數(shù)據(jù)區(qū),但是該段中的數(shù)據(jù)沒有經(jīng)過初始化。因此它只會在目標(biāo)文件中被標(biāo)識,而不會真正稱為目標(biāo)文件中的一段,該段將會在運行時產(chǎn)生。未初始化數(shù)據(jù)段只在運行的初始化階段才會產(chǎn)生,因此它的大小不會影響目標(biāo)文件的大小。

      在C語言的程序中,對變量的使用還有以下幾點需要注意:

      1.函數(shù)體中定義的變量通常是在棧上,不需要在程序中進行管理,由編繹器處理。

      2.用malloc,calloc,realloc等分配內(nèi)存的函數(shù)所分配的內(nèi)存空間在堆上,程序必須保證在使用free釋放,否則會發(fā)生內(nèi)存泄漏。

      3.所有函數(shù)體外定義的是全局變量,加了static后的變量不管是在函數(shù)內(nèi)部或外部都放在全局區(qū)。

      4.使用const定義的變量將放于程序的只讀數(shù)據(jù)區(qū)。

      三:程序中段的使用

      下面用一個簡單的例子來說明C語言中變量和段的對應(yīng)關(guān)系。C語言程序中的全局區(qū)(靜態(tài)區(qū)),實際對應(yīng)著下述幾個段:RO Data; RW Data ; BSS Data.

      一般來說,直接定義的全局變量在未初始化數(shù)據(jù)區(qū),如果該變量有初始化則是在已初始化數(shù)據(jù)區(qū)(RW Data),加上const則將放在只讀數(shù)據(jù)區(qū)。

      const char ro[ ] = {"this is read only data"}; //只讀數(shù)據(jù)區(qū)

      static char rw_1[ ] ={"this is global read write data"}; //已初始化讀寫數(shù)據(jù)段

      char BSS_1[ 100]; //未初始化數(shù)據(jù)段

      const char *ptrconst ="constant data"; //字符串放在只讀取數(shù)據(jù)段

      int main()

      {

      short b; //在棧上,占用2個字節(jié)

      char a[100]; //在棧上開辟100個字節(jié), 它的值是其首地址

      char s[ ]="abcdefg"; //s在棧上,占用4個字節(jié),"abcdefg"本身放置在只讀數(shù)據(jù)存儲區(qū),占8個字節(jié)

      char *p1; //p1在棧上,占用4個字節(jié)

      char *p2="123456"; //p2 在棧上,p2指向的內(nèi)容不能改,“123456”在只讀數(shù)據(jù)區(qū)

      static char rw_2[ ]={"this is local read write data"};//局部已初始化讀寫數(shù)據(jù)段

      static char BSS_2[100]; //局部未初始化數(shù)據(jù)段

      static int c = 0; //全局(靜態(tài))初始化區(qū)

      p1=(char *)malloc(10 * sizeof(char ) ); //分配內(nèi)存區(qū)域在堆區(qū)

      strcpy(p1,"xxxx"); //“XXXX”放在只讀數(shù)據(jù)區(qū),占5個字節(jié)

      free(p1); //使用free釋放p1所指向的內(nèi)存

      return 0;

      }

      讀寫數(shù)據(jù)段包含了憶初始化的全局變量 static char rw_1[ ]以及局部靜態(tài)變量static rw_2[ ].其差別在于編繹時,是在函數(shù)內(nèi)部使用的還是可以在整個文件中使用。對于rw_1[] 無論有無static 修飾,其都將被放置在讀寫數(shù)據(jù)區(qū),只是能否被其它文件引用與否。對于后者就不一樣了,它是局部靜態(tài)變量,放置在讀寫數(shù)據(jù)區(qū),如果沒static修飾,其意義完全改變,它將會是開辟在?臻g的局部變量,而不是靜態(tài)變量,在這里rw_1[],rw_2[]后沒具體數(shù)值,表示靜態(tài)區(qū)大小同后面字符串長度決定。

      對于未初始化數(shù)據(jù)區(qū)BSS_1[100]與BSS_2[100],其區(qū)別在于前者是全局變量,在所有文件中都可以使用;后者是局部變量,只在函數(shù)內(nèi)部使用。未初始化數(shù)據(jù)段不設(shè)置后面的初始化數(shù)值,因此必須使用數(shù)值指定區(qū)域的大小,編繹器將根據(jù)大小設(shè)置BSS中需要增加的長度。

      ?臻g主要用于以下3數(shù)據(jù)的存儲:

      1.函數(shù)內(nèi)部的動態(tài)變量

      2.函數(shù)的參數(shù)

      3.函數(shù)的返回值

    說點什么吧
    • 全部評論(0
      還沒有評論,快來搶沙發(fā)吧!