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