1. 程式人生 > >c中堆棧的理解

c中堆棧的理解

寄存器變量 自動變量 分布圖 外部 理解 靜態變量 spa 靜態局部變量 全局

一直對堆棧的使用以及全局變量、靜態全局變量、局部變量、靜態局部變量、初始化的全局變量、未初始化的全局變量、初始化的局部變量、未初始化的局部變量理解的不是很清楚,今天抽個時間來總結以下這方面的知識:

1.首先心中要有一個內存分布圖,最上面肯定是命令行和環境參數、往下依次是棧、堆、bss段、數據段、代碼段

  • 是從上往下讀的,所以棧放在最上面,棧裏面一般存放的是局部變量,但是如果是static的靜態局部變量那麽其存儲在全局初始化區中也就是數據段中,不管是初始化的局部變量還是未初始化的局部變量
  • 中存放的是程序員可操控的內存,一般用malloc()申請,用free釋放().
  • bss段用來存放未初始化的全局變量和靜態變量,(全局變量未初始化時默認為0的一段區域)
  • 數據段用來存放已經初始化的全局變量和靜態變量
  • 代碼段用來存放程序中的代碼和常量

2.棧:通常指用來存放程序中用戶臨時創建的局部變量、函數形參、數組(局部變量未初始化則默認為垃圾值),不包括static聲明的變量,static意味著在數據段中存放變量。棧可以看成時一個寄存、交換臨時數據的內存區。它是由操作系統分配的,內存的申請與回收都由OS管理。。

3.用static聲明局部變量:有時希望函數中的局部變量的值在函數調用後不消失而保留原值,這時就應該指定局部變量為“靜態局部變量”用關鍵字static進行聲明。

4。對靜態局部變量的說明:

  • 靜態局部變量屬於靜態存儲類別,在驚天存儲區中分配存儲單元。在程序整個運行期間都不釋放。而自動變量屬於動態存儲類別,占動態存儲類別,占動態存儲空間,函數調用結束後即釋放。
  • 靜態局部變量在編譯時賦初值,即只賦值一次,而對自動變量付初值實在函數調用時進行,每調用一次函數重新給一次初值,相當於執行一次賦值語句。
  • 如果在定義局部變量時不賦初值的話,則對靜態局部變量來說,編譯時自動賦初值0,而對自動變量來說,如果不賦初值的話是要給不確定的值。

5.register變量

  • 為了提高效率,c語言允許將局部變量的值販子啊cpu中的寄存器中,這種變量叫“寄存器變量”,用關鍵字register做聲明

6.extern

  • 外部變量(即全局變量)是在函數的外部定義的,它的作用域為從變量定義處開始,到本程序文件的末尾。如果外部變量不在文件的開頭定義,其有效的作用範圍只限於定義處到文件終了。如果在定義點之前的函數想引用該外部變量,則應該在引用之前用關鍵字extern對該變量作“外部變量聲明”。表示該變量是一個已經定義的外部變量。有了此聲明,就可以從“聲明”處起,合法地使用該外部變量#include

7.下面是對一個程序的舉例說明

#include//全局區

int g_n1 = 1;//全局初始化區

char g_c2 ; //全局未初始化區也就是bss段

void funtion()

{

int a = 1;

}

int main(void)

{

int nNum = 1; //棧區

char cStr2[] = "123"; //棧區

char *cStr1 = "hello"; //cStr1在棧區,hello\0在常量區

static int nNum1 = 0; //全局初始化區

char *pCStr = (char *)malloc(10); //分配10字節區域在堆區

strcpy(pCStr, "666"); //666放在常量區

printf("程序代碼區的地址\n");

printf("funtion=%08X\n", funtion);

printf("文字常量區 常量的地址\n");

printf("&cStr1=%08X\n", &cStr1);

printf("&pCStr=%08X\n", &pCStr);

printf("全局區變量的地址\n");

printf("&g_n1=%08X\n", &g_n1);

printf("&g_c2=%08X\n", &g_c2);

printf("&nNum1=%08X\n", &nNum1);

printf("棧區 變量的地址\n");

printf("&nNum=%08X\n", &nNum);

printf("&cStr2=%08X\n", &cStr2);

printf("堆區 空間的地址\n");

printf("pCStr=%08X\n", pCStr);

free(pCStr);//釋放

system("pause");

return 0;

}

c中堆棧的理解