C語言 存儲類型
| 類型 |
作用域 |
生命周期 |
存儲位置 |
| auto變量 |
一對{}內 |
當前函數 |
棧區 |
| static局部變量 |
一對{}內 |
整個程序運行期 |
初始化在data段,未初始化在BSS段 |
| extern變量 |
整個程序 |
整個程序運行期 |
初始化在data段,未初始化在BSS段 |
| static全局變量 |
當前文件 |
整個程序運行期 |
初始化在data段,未初始化在BSS段 |
| extern函數 |
整個程序 |
整個程序運行期 |
代碼區 |
| static函數 |
當前文件 |
整個程序運行期 |
代碼區 |
| register變量 |
一對{}內 |
當前函數 |
運行時存儲在CPU寄存器 |
| 字符串常量 |
當前文件 |
整個程序運行期 |
data段 |
內存分區
一、內存分區說明
代碼區(text segment)
加載的是可執行文件代碼段,所有的可執行代碼都加載到代碼區,這塊內存是不可以在運行期間修改的。
未初始化數據區(BSS)
加載的是可執行文件BSS段,位置可以分開亦可以緊靠數據段,存儲於數據段的數據(全局未初始化,靜態未初始化數據)的生存周期為整個程序運行過程。
全局初始化數據區/靜態數據區(data segment)
加載的是可執行文件數據段,存儲於數據段(全局初始化,靜態初始化數據,文字常量(只讀))的數據的生存周期為整個程序運行過程。
棧區(stack)
棧是一種先進后出的內存結構,由編譯器自動分配釋放,存放函數的參數值、返回值、局部變量等。在程序運行過程中實時加載和釋放,因此,局部變量的生存周期為申請到釋放該段棧空間。
堆區(heap)
堆是一個大容器,它的容量要遠遠大於棧,但沒有棧那樣先進后出的順序。用於動態內存分配。堆在內存中位於BSS區和棧區之間。一般由程序員分配和釋放,若程序員不釋放,程序結束時由操作系統回收。
二、內存分區拓撲


內存數據存儲
一、視圖說明
程序在加載到內存前,代碼區和全局區(data和bss)的大小就是固定的,程序運行期間不能改變。然后,運行可執行程序,系統把程序加載到內存,除了根據可執行程序的信息分出代碼區(text)、數據區(data)和未初始化數據區(bss)之外,還額外增加了棧區、堆區。


二、案例說明
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <string.h> #include <stdlib.h> #include <math.h> #include <time.h> //安全的常量、存儲區域為:數據區->常量區 const int abc = 123; // 未初始化:全局變量 int a1; // 初始化:全局變量 int b1 = 10; // 未初始化:靜態全局變量 static int c1; // 始化化:靜態全局變量 static int d1 = 10; int main(void) { // 初始化:局部變量 int e1 = 10; // 未初始化:靜態局部變量 static int f1; // 初始化:靜態局部變量 static int h1 = 10; // 字符串常量 char* p = "hello world"; // 數組 int arr[] = { 1,2,3,4 }; // 指針 int* pp = arr; printf("未初始化全局變量:%p\n", &a1); printf("初始化全局變量:%p\n", &b1); printf("未初始化靜態全局變量:%p\n", &c1); printf("初始化靜態全局變量:%p\n", &d1); printf("局部變量:%p\n", &e1); printf("未初始化靜態局部變量:%p\n", &f1); printf("初始化靜態局部變量:%p\n", &h1); printf("字符串常量:%p\n", p); printf("數組:%p\n", arr); printf("指針變量:%p\n", pp); printf("指針地址:%p\n", &pp); return 0; }
