1、變量有哪些存儲類型?
變量的存儲類型由“存儲類型指明符”來說明。存儲類型指明符可以是下列類鍵字之一:
auto
register
extern
static
下面是詳細的解釋:
auto 存儲類指明符--用于說明具有局部作用域的變量,它表示變量具有局部(自動)生成期,但由于它是所有局部作用域變量說明的缺省存儲類指明符,所以使用得很少。要注意的是,所有在函數內部定義的變量都是局部變量,函數內部定義的變量其作用域只在函數內部。它的生存期為該函數運行期間,一旦離開這個函數或這個函數終止,局部變量也隨之消失。
register 存儲類指明符--當聲明了這個指明符后,編譯程序將盡可能地為該變量分配CPU內部的寄存器作為變量的存儲單元,以加快運行速度。注意,寄存器與存儲器是不同的。寄存器一般在CPU內部,而存儲器一般指外部的(比如內存條),CPU內部的寄存器其運算速度是很高的。當寄存器已分配完畢,就自動地分配一個外部的內存。它的作用等價于auto,也只能用于局部變量和函數的參量說明。
static 存儲類指明符--表示變量具有靜態生成期。static變量的的特點是它離開了其作用域后,其值不會消失。
當回到該作用域之后又可以繼續使用這個static變量的值。
例:利用static變量統計調用函數的次數
int two(); /*函數原型說明*/
void main()
{
int a=0;
a=two(); /*a的值等于1*/
a=two() /*a的值等于2*/
a=two(); /*a的值等于3*/
}
int two()
{
static int b=0; /*定義了一個局部的static變量*/
b++;
return b;
}
如果不是一個static變量就不會有這個效果了
int two(); /*函數原型說明*/
void main()
{
int a=0;
a=two(); /*a的值等于1*/
a=two() /*a的值等于1*/
a=two(); /*a的值等于1*/
}
int two()
{
int b=0;
b++;
return b;
}
變量a的值總是1,原因是在函數two()中,變量b不是一個static變量,其值隨著離開two函數就消失了,當回到two函數時又被重新賦值0。
extern 存儲類指明符--一般用在工程文件中。在一個工程文件中因為有多個程序文件,當某一個變量在一個程序文件中定義了之后,如果在另一個程序文件中予以定義,就會出現重復定義變量的錯誤。使用extern存儲類型指明符就可以指出在該文件外部已經定義了這個變量。extern變量的作用域是整個程序。
2、變量存儲在內存的什么地方?
1)變量可以存儲在內存的不同地方,這依賴于它們的生成期。在函數上部定義的變量(全局變量或static外部變量)和在函數內部定義的static變量,其生存期就是程序運行的全過程。這些變量被存儲在數據段(Data Segment)中。數據段是在內存中為這些變量留出的一段大小固定的空間,它分為二部分,一部分用來初始化變量,另一部分用來存放未初始化的變量。
2)在函數內部定義的auto變量(沒有用關鍵字static定義的變量)的生成期從程序開始執行其所在的程序塊代碼時開始,到程序離開該程序塊時為止。作為函數參數的變量只在調用該函數期間存在。這些變量被存儲在棧(stack)中。棧是內存中的一段空間,開始很小,以后逐漸自動變大,直到達到某個預定義的界限。
3)當用malloc等函數給指針分配一個地址空間的時候,這個分配的內存塊位于一段名為“堆(heap)”的內存空間中。堆開始時很小,但調用malloc或clloc等內存分配函數時它就會增大。堆可以和數據段或棧共用一個內存段,也可以有它自己的內存段,這完全取決于編譯選項和操作系統。與棧相似,堆也有一個增長界限,并且決定這個界限的規則與棧相同。