變量類型編程
常量是不可變的值,能夠用宏來定義,好比 #define PI 3.14windows
變量的值是能夠變化的,因爲編程的不一樣需求,對變量有各類要求,數組
好比:變量的生命週期,變量的初始狀態,變量的有效區域(做用域),變量的存儲地和存儲區域的大小。安全
爲了知足這些不一樣的編程需求,C語言發明者設置瞭如下變量:多線程
1 不一樣數據類型的變量。好比 char,int,float等。(變量在內存中佔用地址大小由數據類型決定)架構
2 全局變量函數
3 局部變量spa
4 靜態變量:包括靜態全局變量和靜態局部變量線程
5 寄存器變量3d
6 外部變量
C語言中,除了基本類型外,開發者能夠經過typedef來定義本身須要的數據類型。好比:
typedef int INT;
typedef unsigned int UINT;
typedef struct student
{
char *name;
int age;
}STUDENT;
若是結構體student不用typedef重定義的話,定義結構體變量時:struct student stu1;
使用typedef重定義之後,咱們只須要STUDENT stu1;便可。
1 全局變量。在函數外定義,可被全部函數使用。可是在多線程訪問時,須要注意多線程安全問題。
2 局部變量。在函數內部聲明。只有在函數執行時,局部變量才存在,函數執行完局部變量就消失。
3 靜態變量。分配在內存中的數據段中,在C程序運行的整個過程當中一直保留,靜態變量能夠定義成靜態全局變量和靜態局部變量。
①靜態全局變量在程序的整個運行期間都存儲且內存地址不會改變。
②靜態局部變量只在聲明它的函數內有效,且在下一次調用時還保留上次調用結束時的值(只初始化一次)。
4 寄存器變量。 寄存器變量存放在CPU的寄存器中,使用寄存器變量比內存變量操做速度快得多。
只有整型和字符型變量能夠定義爲寄存器變量。好比:
register int i;
register char c;
①因爲CPU中寄存器有限,儘可能減小使用寄存器的數量和佔用時間,用完立刻釋放。
②寄存器變量不能定義爲全局變量,也不能定義在結構體和類中。
③若是寄存器已經無可用資源,寄存器變量將轉化爲普通局部變量。
extern:
在大型程序中,會將一個大型的程序分紅多個獨立的模塊和文件分別編譯,而後統一連接在一塊兒。爲了解決全局變量和函數的共用問題,
引入了extern關鍵字。只須要在一個文件中定義全局變量和函數,在另外一個文件中要用到這些變量和函數時,只須要將那個文件中的變量和
函數說明覆制過來,而後在前面加上extern就能夠。這樣就等於告訴編譯器,這些變量和函數已經在別的文件中定義。
變量的存儲空間
代碼和數據,都要加載到內存中,才能被運行和訪問。X86系統中,內存的有效範圍爲4GB。
①高2GB內存地址爲內核空間,用來存放內核的代碼和數據
②低2GB爲用戶空間,運行進程的用戶態代碼,且低2GB的內存是進程私有空間,一個進程不能跨進程訪問別的進程空間的用戶態地址。
如圖所示,程序在內存中分爲以下幾部分:
1 .text 代碼段,這段是存放代碼的
2 .rdata 只讀數據段,不能修改,存放常量,字符常量,const常量。
3 .data 數據段 存放已經初始化好的全局變量和靜態變量
4 .bss 存放未初始化的全局變量和靜態變量
PS:.rdata,.data,.bss都是存放數據的段。.rdata段和.data段的值都在編譯的時候就肯定了,而且將值編譯進了
可執行文件,通過反彙編就能夠找到。已初始化的全局變量放在.data段,未初始化的變量放在bss段。
5 .stack 棧段,棧中存放普通的局部變量(非靜態局部變量),形參,返回地址等。棧的大小有限制:
windows應用層棧大小默認爲1MB;普通內核棧的大小是固定的,由系統根據CPU架構決定,X86系統上12KB,X64系統24KB,安騰系統32KB
Linux應用層棧大小默認爲10MB,內核棧大小4KB或8KB
6 堆: 能夠存聽任意數據
綜上:
①全局初始化變量存放在靜態存儲區的.data段
②全局未初始化變量存放在靜態存儲區的.bss段
③局部變量存放在棧
④全局靜態變量和局部靜態變量存放在靜態存儲區的.data段和.bss段
⑤常量存放在靜態區的.rdata段。.rdata區域是隻讀內存,不能修改
⑥寄存器變量存放在寄存器中 (若是寄存器資源不夠,仍是放在內存中)
變量的做用域
變量的做用域指變量能在代碼什麼地方能夠被訪問到。
1 全局變量: 全部程序中的代碼都能訪問。
若是全局變量在一個源文件中定義,在另外一個源文件中訪問,須要用extern關鍵字導入。多線程訪問全局變量注意安全問題
2 靜態全局變量: 在同一個源文件中能夠訪問,不一樣源文件不可訪問,也不能用extern來導入。
3 局部變量:只能在函數內部訪問
4 靜態局部變量:只能函數內部訪問
5 寄存器變量:只能在函數內部訪問
變量的生命週期
變量的生命週期是指變量在程序運行期間的有效時間
1 全局變量:整個程序運行期間有效
2 靜態全局變量:整個程序運行期間有效
3 局部變量:函數範圍內或代碼塊範圍內有效
4 靜態局部變量:整個程序運行期間有效
5 寄存器變量:函數範圍內或代碼塊範圍內有效
習題:分析下列程序中每一個變量的存儲位置,做用域,與生命週期
int a = 0;
char *p1;
static int x = 10;
void main(void)
{
int b = 0;
char s[] = "123";
char *p2;
char *p3 = "hello, world";
static int c =0;
p1 = (char *)malloc(128);
p2 = (char *)malloc(256);
free(p1);
free(p2);
}
分析與解答:下面給出了上面各變量的類型,存儲,做用域和生命週期的詳細的概括:
int a = 0; //全局初始化變量
char *p1; //全局未初始化變量
static int x = 10;//全局初始化靜態變量
void main(void)
{
int b = 0; //局部變量
char s[] = "123"; //s局部變量,字符數組,用"123"字符串常量進行初始化
char *p2; //局部變量
char *p3 = "hello, world"; //p3局部變量,字符指針,指向"hello, world"字符串常量
static int c =0; //靜態局部變量,已初始化
p1 = (char *)malloc(128); //p1,p2指向堆
p2 = (char *)malloc(256);
free(p1); //顯示釋放p1,p2指向的堆內存
free(p2);
}