C語言編程常見問題解答之變量和數(shù)據(jù)存儲

字號:

第2章 變量和數(shù)據(jù)存儲
     C語言的強(qiáng)大功能之一是可以靈活地定義數(shù)據(jù)的存儲方式。C語言從兩個方面控制變量的性質(zhì):作用域(scope)和生存期(lifetime)。作用域是指可以存取變量的代碼范圍,生存期是指可以存取變量的時間范圍。
     作用域有三種:
     1. extern(外部的) 這是在函數(shù)外部定義的變量的缺省存儲方式。extern變量的作用域是整個程序。
     2.static(靜態(tài)的) 在函數(shù)外部說明為static的變量的作用域為從定義點(diǎn)到該文件尾部;在函數(shù)內(nèi)部說明為static的變量的作用域為從定義點(diǎn)到該局部程序塊尾部。
     3.a(chǎn)uto(自動的) 這是在函數(shù)內(nèi)部說明的變量的缺省存儲方式。auto變量的作用域為從定義點(diǎn)到該局部程序塊尾部。
     變量的生存期也有三種,但它們不象作用域那樣有預(yù)定義的關(guān)鍵字名稱。第一種是extern和static變量的生存期,它從main()函數(shù)被調(diào)用之前開始,到程序退出時為止。第二種是函數(shù)參數(shù)和auto變量的生存期,它從函數(shù)調(diào)用時開始,到函數(shù)返回時為止。第三種是動態(tài)分配的數(shù)據(jù)的生存期,它從程序調(diào)用malloc()或calloc()為數(shù)據(jù)分配存儲空間時開始,到程序調(diào)用free()或程序退出時為止。
     2.1 變量存儲在內(nèi)存(memory)中的什么地方?
     變量可以存儲在內(nèi)存中的不同地方,這依賴于它們的生存期。在函數(shù)外部定義的變量(全局變量或靜態(tài)外部變量)和在函數(shù)內(nèi)部定義的static變量,其生存期就是程序運(yùn)行的全過程,這些變量被存儲在數(shù)據(jù)段(datasegment)中。數(shù)據(jù)段是在內(nèi)存中為這些變量留出的一段大小固定的空間,它分為兩部分,一部分用來存放初始化變量,另一部分用來存放未初始化變量。
     在函數(shù)內(nèi)部定義的auto變量(沒有用關(guān)鍵字static定義的變量)的生存期從程序開始執(zhí)行其所在的程序塊代碼時開始,到程序離開該程序塊時為止。作為函數(shù)參數(shù)的變量只在調(diào)用該函數(shù)期間存在。這些變量被存儲在棧(stack)中。棧是內(nèi)存中的一段空間,開始很小,以后逐漸自動增大,直到達(dá)到某個預(yù)定義的界限。在象DOS這樣的沒有虛擬內(nèi)存(virtual memory)的系統(tǒng)中,這個界限由系統(tǒng)決定,并且通常非常大,因此程序員不必?fù)?dān)心用盡棧空間。關(guān)于虛擬內(nèi)存 的討論,請參見2.3。
     第三種(也是最后一種)內(nèi)存空間實際上并不存儲變量,但是可以用來存儲變量所指向的數(shù)據(jù)。如果把調(diào)用malloc()函數(shù)的結(jié)果賦給一個指針變量,那么這個指針變量將包含一塊動態(tài)分配的內(nèi)存的地址,這塊內(nèi)存位于一段名為“堆(heap)”的內(nèi)存空間中。堆開始時也很小,但當(dāng)程序員調(diào)用malloc()或calloc()等內(nèi)存分配函數(shù)時它就會增大。堆可以和數(shù)據(jù)段或棧共用一個內(nèi)存段(memorysegment),也可以有它自己的內(nèi)存段,這完全取決于編譯選項和操作系統(tǒng)。
     與棧相似,堆也有一個增長界限,并且決定這個界限的規(guī)則與棧相同。
     請參見:
     1.1 什么是局部程序塊(10calblock)?
     2.2 變量必須初始化嗎?
     2.3 什么是頁抖動(pagethrashing)?
     7.20 什么是棧(stack)?
     7.21 什么是堆(heap)7 .
     2.2 變量必須初始化嗎?
     不。使用變量之前應(yīng)該給變量一個值,一個好的編譯程序?qū)椭惆l(fā)現(xiàn)那些還沒有被給定一個值就被使用的變量。不過,變量不一定需要初始化。在函數(shù)外部定義的變量或者在函數(shù)內(nèi)部用static關(guān)鍵字定義的變量(被定義在數(shù)據(jù)段中的那些變量,見2.1)在沒有明確地被程序初始化之前都已被系統(tǒng)初始化為0了。在函數(shù)內(nèi)部或程序塊內(nèi)部定義的不帶static關(guān)鍵字的變量都是自動變量,如果你沒有明確地初始化這些變量,它們就會具有未定義值。如果你沒有初始化一個自動變量,在使用它之前你就必須保證先給它賦值。
     調(diào)用malloc()函數(shù)從堆中分配到的空間也包含未定義的數(shù)據(jù),因此在使用它之前必須先進(jìn)行初始化,但調(diào)用calloc()函數(shù)分配到的空間在分配時就已經(jīng)被初始化為0了。
     請參見:
     1.1 什么是局部程序塊(10calblock)?
     7.20 什么是棧(stack)?
     7.21 什么是堆(heap)?
     2.3 什么是頁抖動(pagethrashing)?
     有些操作系統(tǒng)(如UNIX和增強(qiáng)模式下的Windows)使用虛擬內(nèi)存,這是一種使機(jī)器的作業(yè)地址空間大于實際內(nèi)存的技術(shù),它是通過用磁盤空間模擬RAM(random—access memory)來實現(xiàn)的。