變數儲存域

2021-05-23 11:30:26 字數 2465 閱讀 7334

變數儲存域

2010-09-23 15:43

1.1 變數儲存域

1.1.1 乙個示例

pang123hui首先提供了乙個網上流傳的學習**示例:

int a = 0; //全域性區

void main()

int b; //棧

char s = 「abc」; //s在棧,abc在文字常量區

char *p1,*p2; //棧

char *p3 = "123456"; //123456在常量區,p3在棧上

static int c =0; //全域性區

p1 = (char *)malloc(10); //p1在棧,分配的10位元組在堆

p2 = (char *)malloc(20); //p2在棧,分配的20位元組在堆

strcpy(p1, "123456"); //123456放在常量區

這個**示例中出現了「全域性區」,「棧」,「文字常量區」,「堆」等詞語。為了統一,我們使用《c專家程式設計》中的說法:堆疊段,bss段,資料段,文字段。

各個段的作用如下:

1、 文字段:包含程式的指令,它在程式的執行過程中一般不會改變。

2、 資料段:包含了經過初始化的全域性變數和靜態變數,以及他們的值。

3、 bss段:包含未經初始化的全域性變數和靜態變數。

4、 堆疊段:包含了函式內部宣告的區域性變數。

當然,上面段的作用不僅於此,具體的作用會在下面的知識點中介紹。

1.1.2 通過**測試變數的儲存位置

linux下可以通過系統命令「size」檢視可以執行程式各個段的大小。但是,可執行程式中的段結構和執行中程式在記憶體中的段結構並不完全相同,但是有一定的對映關係。具體如下圖所示(資訊來自《c專家程式設計》):

下面通過**示例和「size」來研究變數的儲存區域。

test.c

int main()

return 1;

編譯,並且檢視可執行程式各個段的大小:

更改test.c:

int g_data;

int main()

return 1;

編譯,並且檢視可執行程式各個段的大小:

可以發現,文字段,資料段都沒有傳送變化,而bss段增加了4個位元組。

結論1:未初始化的全域性變數儲存在bss段中

繼續:int g_data = 1;

int main()

return 1;

編譯:可以發現,bss段和文字段相同,而資料段增加了4個位元組。

結論2:經過初始化的全域性變數儲存在資料段中

繼續:int main()

static int g_data;

return 1;

編譯:可以發現,文字段,資料段都沒有傳送變化,而bss段增加了4個位元組。

結論3:未初始化的靜態變數儲存在bss段中

繼續:int main()

static int g_data = 1;

return 1;

編譯:可以發現,bss段和文字段相同,而資料段增加了4個位元組。

結論4:經過初始化的靜態變數儲存在資料段中

繼續:int main()

int i_data = 1;

return 1;

編譯:可以發現,bss段和和資料段相同,而文字段增加了16個位元組。區域性變數會在執行的時候在堆疊段中生成,函式執行完畢後釋放。

結論5:函式內部宣告的區域性變數儲存在堆疊段中

繼續:const int g_data = 1;

int main()

return 1;

編譯:把全域性變數定義為「const」後,也許你會感到奇怪,怎麼bss段和資料段都沒有發生變化,而文字段卻增加了4個位元組。

結論6:const修飾的全域性變數儲存在文字段中

那麼,const的區域性變數?

繼續:int main()

const int i_data = 1;

return 1;

編譯:結論7:const修飾的區域性變數儲存在堆疊段中

繼續:char *pstr = "";

int main()

return 1;

編譯:在做一下更改:

char *pstr = "123456789";

int main()

return 1;

編譯:可以發現,前後資料段和bss段大小均未發生變化,而文字段增加了9個位元組。

結論8:字串常量儲存在文字段中

1.1.3 結論

1、 經過初始化的全域性變數和靜態變數儲存在資料段中。

2、 未經初始化的全域性變數和靜態變數儲存在bss段。

3、 函式內部宣告的區域性變數儲存在堆疊段中。

4、 const修飾的全域性變數儲存在文字段中,const修飾的區域性變數儲存在堆疊段中。

5、 字串常量儲存在文字段中。

1.1.4 擴充套件閱讀

《c專家程式設計》第6章——詳細介紹各個段的作用

block變數儲存域

將block賦值給strong 型別的block變數,或者賦值給strong 修飾的物件型別中的block成員變數時,block會從棧複製到堆上。那 block變數會有什麼變化呢?其實,當block 被從棧複製到堆上時,block中使用到的變數也會從棧賦值到堆上。當block被從棧複製到堆前後,bl...

變數儲存型別 作用域

auto 作用域和壽命 只能做區域性變數 在函式內或復合語句內定義的自動變數可以省略auto,而在外部定義的無auto的變數顯然不是自動變數 外部變數,即 全域性變數 的壽命和作用域是全域性的 register 作用域和壽命 同auto,即 區域性可見 分配通用暫存器的條件 1 有空閒的暫存器 2 ...

變數的作用域和儲存方式

按作用域可分為 區域性變數 函式級區域性變數,復合語句級區域性變數,這種型別的變數在本函式或本復合語句內有效,在其他範圍內無效。按儲存方式可分為 靜態儲存區儲存 全域性變數和static區域性變數全部存放在靜態儲存區,從定義開始占用記憶體一直到本檔案結束釋放記憶體,存放在靜態儲存區的區域性變數並不隨...