C語言中的static , extern關(guān)鍵字 看了《POINTER ON C》中對C語言中extern , static關(guān)鍵字的介紹,,萌發(fā)了對此小小總結(jié)一下的沖動。 看了幾個網(wǎng)頁,,覺得對其總結(jié)的不是很全面,。更覺得有必要在這個地方整理,mark下了。 在這之前,,不得不先說下作用域,,鏈接屬性,存儲類型,。 1. 作用域(scope):當(dāng)變量在程序的某個部分被聲明時,,它只有在程序的一定區(qū)域才能被訪問。 有文件作用域,,函數(shù)作用域,,代碼塊作用域和原型作用域。 1.1 代碼塊作用域 :位于一對花括號之間的所有語句稱為一個代碼塊,。任何在代碼塊的開始位置 聲明的標識符都具有“代碼塊作用域”,。 1.2 文件作用域:任何在所有代碼塊之外聲明的標志符都具有文件作用域,表示這些標志符從他們 的聲明處直到它所在的源文件結(jié)尾處都是可以訪問的,。 1.3 原型作用域:只適用在函數(shù)原型中聲明的參數(shù)名,。 1.4 函數(shù)作用域:作用域在函數(shù)里面的,只是適用于語句標簽,,要求函數(shù)中所有的語句標簽必須唯一,。 2. 鏈接屬性 當(dāng)組成一個程序的各個源文件分別被編譯之后,所有的目標文件以及那些從一個或多個函數(shù)庫中引用 的函數(shù)鏈接在一起,,形成可執(zhí)行程序,。標識的鏈接屬性決定如何處理在不同文件中出現(xiàn)的標識符。 鏈接屬性一共有3種—— external (外部),,internal (內(nèi)部)和none(無),。沒有鏈接屬性的標識 符總是被當(dāng)作單獨的的個體,也就是說該標識符的多個聲明被當(dāng)作獨立不同的實體,。屬于internal鏈接 屬性的標識符在同一個源文件內(nèi)的所有聲明都指同一個實體,,但位于不同源文件的多個聲明則分屬不同 的實體,。最后,屬于external鏈接屬性的標識符不論聲明多少次,,位于幾個源文件都表示同一個實體,。 3. 存儲類型 變量的存儲類型是指存儲變量值的內(nèi)存類型。變量的存儲類型決定變量何時創(chuàng)建,,何時銷毀以及它的 值將保持多久,。有三個地方可以用于存儲變量:普通內(nèi)存,運行時堆棧,,硬件寄存器,。凡是在任何代碼 塊之外聲明的變量總是存儲于靜態(tài)內(nèi)存中,也就是不屬于堆棧的內(nèi)存,。靜態(tài)變量在程序運行之前創(chuàng)建,, 在程序的整個執(zhí)行期間始終存在。 在代碼塊內(nèi)部聲明的變量的缺省存儲類型為auto .它存儲與堆棧中,。在程序執(zhí)行到聲明自動變量的 代碼塊時,,自動變量才被創(chuàng)建,當(dāng)程序的執(zhí)行流離開該代碼塊時,,這些自動變量自行銷毀,。 關(guān)鍵字register可以用于自動變量的聲明,提示他們應(yīng)該存儲于機器的硬件寄存器而不是內(nèi)存中,。 寄存器變量的創(chuàng)建和銷毀時間和自動變量相同,,但它需要一些額外的工作。 static , extern 用于修飾變量 : 1. static如果修飾的是代碼塊之外的變量,,即靜態(tài)全局變量,,此變量的作用域為文件作用域,存儲在 全局數(shù)據(jù)區(qū),,鏈接屬性為internal,。 也就是說,只有在全局靜態(tài)變量的源文件中才能訪問(使用) 此變量,。此變量的生命周期是程序運行的整個過程,。鏈接時,鏈接器在本源文件中查找其聲明,。 A、該變量在全局數(shù)據(jù)區(qū)分配內(nèi)存,。 B,、初始化:如果不顯式初始化,那么將被隱式初始化為0,。 C,、訪變量只在本源文件可見,,嚴格的講應(yīng)該為定義之處開始到本文件結(jié)束。 第一,, 不必擔(dān)心另外源文件使用它的名字,該名字在源文件中是唯一的,。 第二,, 源文件的全局變量不能被其他源文件所用,不能被其他的源文件所修改,,保證變量的值是可靠的,。 如果我們要在其他文件里面訪問全局靜態(tài)變量,我們可以定義對應(yīng)的set 和 get接口(類似C++),,將 對應(yīng)的set 和 get接口定義為全局的函數(shù),。 2. static如果修飾的是代碼塊內(nèi)的變量,即靜態(tài)局部變量,。此變量的作用域為代碼塊作用域,,存儲在 全局數(shù)據(jù)區(qū),鏈接屬性為internal,。函數(shù)被多次調(diào)用時,,實際上訪問的是同一塊內(nèi)存區(qū)。對于需要在 函數(shù)內(nèi)部保存狀態(tài),,以備下次函數(shù)調(diào)用時使用的情況,,可以使用static局部變量。 3. extern一般是用來修飾代碼塊之外的變量,,即外部變量,。此類變量的作用域為文件作用域,存儲在 全局存儲區(qū),。生命周期為程序運行的整個過程,。鏈接屬性為external。也就是說,,在定義和聲明(直接 聲明,,或者通過#include包含此變量聲明的頭文件的方式間接聲明)的文件中都可以訪問。 當(dāng)static用來修飾局部變量時,,它就改變了局部變量的存放位置,,將其由原來的棧中存放改為全局靜態(tài) 儲存區(qū),,但是沒有改變變量的作用域,還是局限在局部的{}里。 (局部變量) 當(dāng)static用來修飾全局變量時,,它就改變了全局變量的作用域,,使其不能被別的程序extern,限制在了 當(dāng)前文件里,但是沒有改變其存放位置,,還是在全局靜態(tài)儲存區(qū)。(“還是全局的”) static , extern 用于修飾函數(shù) : 1,、靜態(tài)函數(shù)(注意與類的靜態(tài)成員函數(shù)區(qū)別) 函數(shù)的定義和聲明默認情況下在整個程序中是extern的,,有時候可能需要使某個函數(shù)只在一個源文件中有效, 不能被其他源文件所用,,這時在函數(shù)前面加上static. 定義:在函數(shù)的返回類型前加上static關(guān)鍵字,,函數(shù)即被定義成靜態(tài)函數(shù)。 特點: A,、靜態(tài)函數(shù)只能在本源文件中使用(這是與普通函數(shù)區(qū)別) 第一,, 它允許其他源文件建立并使用同名的函數(shù),而不相互沖突 第二,, 聲明為靜態(tài)的函數(shù)不能被其他源文件所調(diào)用,,因為它的名字不能得到, B,、注意:在文件作用域下聲明的inline函數(shù)默認為static類型,。 2、全局函數(shù) 如果你定義的函數(shù),,是要在多處調(diào)用,,特別是中間件層定義,提供給上層使用的情況,, 此時你需要定義全局函數(shù),,并且在頭文件中對該全局函數(shù)進行聲明(extern void A())。 3. 關(guān)于extern的補充 在cpp程序文件中用到c的庫函數(shù)時用extern,,標明對函數(shù)聲明,,不用C++編譯器去 修飾,而用C編譯器,。 在編譯階段,,編譯器遇到一個變量的時候,先看是否有此變量的聲明,。如果沒有,,則提示編譯 錯誤,找不到這樣的標識,。如果找到了,,則編譯通過。 1.由于靜態(tài)變量作用域是在本源文件,,所以一般不需要聲明,。找到的一般就是其定義了。 2.對于外部變量或函數(shù)。編譯通過后,,在鏈接過程中,鏈接器會在整個工程里面查找 是否有此變量或函數(shù)的定義,。如果沒有,,則鏈接失敗。否則,,鏈接成功,。 static法則: A、若全局變量僅在單個C文件中訪問,,則可以將這個變量修改為靜態(tài)全局變量,,以降低模塊間的耦合度; B、若全局變量僅由單個函數(shù)訪問,,則可以將這個變量改為該函數(shù)的靜態(tài)局部變量,,以降低模塊間的耦合度; C,、設(shè)計和使用訪問動態(tài)全局變量,、靜態(tài)全局變量、靜態(tài)局部變量的函數(shù)時,,需要考慮重入問題,; |
|