c語言目標程式中的段

2021-05-26 19:26:36 字數 4410 閱讀 7764

段的分類

根據c語言的特點,每乙個源程式生成的目標**將包含源程式所需要表達的所有資訊和功能。目標**中各段生成情況如下:

1.**段(code)

**段由程式中的各個函式產生,函式的每乙個語句將最終經過編譯和彙編生成二進位制機器**(具體生成哪種體系結構的機器**由編譯器決定)。

· 順序**

基本數**算(+,-),邏輯運算(&&,||),位運算(&,|,^)等都屬於順序**。

· 選擇**

if,if…else語句等將由編譯器生成選擇**。

· 迴圈**

while(),do…while()語句等將由編譯器生成迴圈**。

對於一些較為複雜的數**算如除法(\),取餘(%)等,雖然它們是c語言的基本運算,但在各種編譯系統中的處理方式卻不一定相同。根據編譯器和體系結構的特點,對它們的處理方式有可能與加減等運算相同,即直接生成處理器的機器**,也有可能轉換成乙個庫函式的呼叫。例如,在沒有除法指令的體系結構中,編譯器在編譯a/b這類除法運算的時候,由於處理器沒有與其對應的指令,因此會使用呼叫庫函式來模擬除法運算。浮點數的處理與之類似:對於支援浮點運算的體系結構,將直接生成浮點**;對於不支援浮點數的處理器,編譯器將會把每乙個浮點運算用庫函式呼叫的方式模擬。

2.唯讀資料段(ro data)

唯讀資料段由程式中所使用的資料產生,該部分資料的特點是在執行中不需要改變,因此編譯器會將該資料放入唯讀的部分中。c語言的一些語法將生成唯讀資料段。

· 唯讀全域性量

例如:定義全域性變數const char a[100]=將生成大小為100個位元組的唯讀資料區,並使用字串"abcdefg"初始化。如果定義為const char a=,沒有指定大小,將根據"abcdefg"字串的長度,生成8個位元組的唯讀資料段。

· 唯讀區域性量

例如:在函式內部定義的變數const char b[100] =;其初始化的過程和全域性量一樣。

· 程式中使用的常量

例如:在程式中使用printf("information \n"),其中包含了字串常量,編譯器會自動把常量"information \n"放入唯讀資料區。

在const char a[100]=中,定義了100個位元組的資料區,但是只初始化了前面的8個位元組(7個字元和表示結束的'\0')。在這種用法中,實際後面的位元組沒有初始化,但是在程式中也不能寫,實際上沒有任何用處。因此,在唯讀資料段中,一般都需要做完全的初始化。

3.讀寫資料段(rw data)

讀寫資料段表示了在目標檔案中一部分可以讀也可以寫的資料區,在某些場合它們又被稱為已初始化資料段。這部分資料段和**段,與唯讀資料段一樣都屬於程式中的靜態區域,但是具有可寫的特點。

· 已初始化全域性靜態變數

例如:在函式外部,定義全域性的變數char a[100]=

· 已初始化區域性靜態變數

例如:在函式中定義static char b[100] =。函式中由static定義並且已經初始化的資料和陣列將被編譯為讀寫資料段。

讀寫資料區的特點是必須在程式中經過初始化,如果只有定義,沒有初始值,則不會生成讀寫資料區,而會定位為未初始化資料區(bss)。如果全域性變數(函式外部定義的變數)加入static修飾符,寫為類似static char a[100]的形式,這表示只能在檔案內使用,而不能被其他檔案使用。

4.未初始化資料段(bss)

未初始化資料段常被稱之為bss(英文block start by symbol的縮寫)。與讀寫資料段類似,它也屬於靜態資料區,但是該段中的資料沒有經過初始化。因此它只會在目標檔案中被標識,而不會真正稱為目標檔案中的乙個段,該段將會在執行時產生。未初始化資料段只有在執行的初始化階段才會產生,因此它的大小不會影響目標檔案的大小。

在c語言的程式中,對變數的使用還有以下幾點需注意:

1.在函式體中定義的變數通常是在棧上,不需要在程式中進行管理,由編譯器處理。

2.用malloc,calloc,realloc等分配記憶體的函式所分配的記憶體空間在堆上,程式必須保證在使用後用free釋放,否則會發生記憶體洩漏。

3.所有函式體外定義的是全域性變數,加了static修飾符後的變數不管在函式內部或者外部都存放在全域性區(靜態區)。

4.使用const定義的變數將放於程式的唯讀資料區。

在c語言中,可以定義static變數:在函式體內定義的static變數只能在該函式體內有效;在所有函式體外定義的static變數,也只能在該檔案中有效,不能在其他的原始檔中使用;對於沒有使用static修飾的全域性變數,可以在其他的原始檔中使用。這些區別是編譯的概念,即如果不按要求使用變數,編譯器會報錯。使用static和沒有使用static修飾的全域性變數最終都將放置在程式的全域性區(靜態區)。

程式中段的使用

本小節使用簡單的例子,說明c語言中變數和段的對應關係。c語言程式中的全域性區(靜態區),實際對應著下述幾個段:

· 唯讀資料段:ro data

· 讀寫資料段:rw data

· 未初始化資料段:bss data

一般來說,直接定義的全域性變數在未初始化資料區,如果該變數有初始化則是在已初始化資料區(rw data),加上const修飾符將放置在唯讀區域(ro data)。

示例1:

const char ro=; /* 唯讀資料段 */

static char rw1=;

/* 已初始化讀寫資料段 */

char bss_1[100]; /* 未初始化資料段 */

const char* ptrconst = "constant data"; /* "constant data"放在唯讀資料段 */

int main()

short b; /* b放置在棧上,占用2個位元組 */

char a[100]; /* 需要在棧上開闢100個位元組,a的值是其首位址 */

char s = "abcde"; /* s在棧上,占用4個位元組 */

/* "abcde "本身放置在唯讀資料儲存區,佔6位元組 */

char *p1; /* p1在棧上,占用4個位元組 */

char *p2 = "123456"; /* "123456"放置在唯讀資料儲存區,佔7位元組 */

/* p2在棧上,p2指向的內容不能更改。 */

static char rw2=;

/* 區域性已初始化讀寫資料段 */

static char bss_2[100]; /* 區域性未初始化資料段 */

static int c = 0; /* 全域性(靜態)初始化區 */

p1= (char *)malloc(10*sizeof(char));

/* 分配的記憶體區域在堆區。 */

t size=3> strcpy(p1, "***x"); /* "***x"放置在唯讀資料儲存區,佔5位元組 */

free(p1); /* 使用free釋放p1所指向的記憶體 */

return 0;

示例1程式中描述了c語言原始檔中語句如何轉換成各個段。

唯讀資料段需要包括程式中定義的const型的資料(如:const char ro),還包括程式中需要使用的資料如"123456"。對於const char ro和const char* ptrconst的定義,它們指向的記憶體都位於唯讀資料區,其指向的內容都不允許修改。區別在於前者不允許在程式中修改ro的值,後者允許在程式中修改ptrconst本身的值。對於後者,改寫成以下的形式,將不允許在程式中修改ptrconst本身的值:

const char* const ptrconst = "constant data";

讀寫資料段包含了已經初始化的全域性變數static char rw1以及區域性靜態變數static char rw2。rw1和rw2的差別只是在於編譯時,是在函式內部使用的還是可以在整個檔案中使用。對於前者,static修飾在於控制程式的其他檔案是否可以訪問rw1變數,如果有static修飾,將不能在其他的c語言原檔案中使用rw1,這種影響針對編譯-連線的特性,但無論有無static,變數rw1都將被放置在讀寫資料段。對於後者rw2,它是區域性的靜態變數,放置在讀寫資料區;如果不使用static修飾,其意義將完全改變,它將會是開闢在棧空間區域性變數,而不是靜態變數。在這裡,rw1和rw2後面的方括號()內沒有數值,表示靜態區的大小由後面字串的長度決定,如果將它們的定義改寫為以下形式:

static char rw1[100]=;

static char rw2[200]=;

則讀寫資料區域的大小直接由後面的數值(100或者200)決定,超出字串長度的空間的內容為0。

未初始化資料段,示例1中的bss_1[100]和bss_2[200]在程式中代表未初始化的資料段。其區別在於前者是全域性的變數,在所有檔案中都可以使用;後者是區域性的變數,只在函式內部使用。未初始化資料段不設定後面的初始化數值,因此必須使用數值指定區域的大小,編譯器將根據大小設定bbs中需要增加的長度。

棧空間包括函式中內部使用的變數如short b和char a[100],以及char *p1中p1這個變數的值。

變數p1指向的記憶體建立在堆空間上,棧空間只能在程式內部使用,但是堆空間(例如p1指向的記憶體)可以作為返回值傳遞給其他函式處理。

C語言結構體中的位段

c語言結構體中的位段 位段的記憶體分配 位段的成員可以是 int unsigned int signed int 或者是 char 屬於整形家族 型別 位段的空間上是按照需要以4個位元組 int 或者1個位元組 char 的方式來開闢的。位段涉及很多不確定因素,位段是不跨平台的,注重可移植的程式應該...

C語言的各個段。

c語言程式經過編譯連線後形成的二進位制映像檔案由棧,堆,資料段和 段組成。其中資料段 由三部分部分組成 唯讀資料段,已經初始化讀寫資料段,未初始化資料段即bbs 1.棧區 stack 又叫堆疊,先進先出,由編譯器自動分配釋放,存放函式的引數值,區域性變數等值。其操作方式類似於資料結構中的棧。2.堆區...

C語言段錯誤

當我在linux下寫c語言的時候經常會遇到段錯誤.所以就來細究一下.段錯誤或段違規 segmentation violation 檢視expert c programming peter van der linden pg.156 解釋到段錯誤是由於記憶體管理單元 mmu 的異常所致,而該異常則通常...