1. 程式人生 > >【VS開發】static、extern分析總結

【VS開發】static、extern分析總結

       對於寫了很多小程式的人,可能static和extern都用的很少,因為static和extern通常在工程量很大時候才能體現優勢很必要性,這就不奇怪linux核心程式碼中“氾濫”著這兩個關鍵詞,而且據我所知,這也是面試經常被問道的,因為這涉及到的底層多一點。下面,就我自己總結的幾點簡要談談:

一、c語言記憶體空間佈局

      下面是google上找的一張c記憶體佈局圖,我先基於這張圖介紹下各個記憶體區域的情況

1、正文(程式碼段):每個程式開始前,都有系統載入程式碼指令到這裡,用於執行,當然都是機器碼

2、初始化的資料段:存放已經初始化的非自動變數,如全域性變數int i=0;等等

3、未初始化的資料段(BSS):存放未初始化的非自動變數,如全域性變數int i;等等

4、堆:動態申請的區域,如malloc、calloc、realloc等產生的

5、棧:自動變數或函式呼叫資訊儲存的區域,如區域性變數int i;等等

二、extern關鍵詞

      這個關鍵詞是用來申明時告訴編譯器,這個變數或函式等可以在別的檔案裡定義,而且可以申明多次,但是定義只能一次。這樣的好處就是多個檔案可以共用一個量。這裡要強調一點,我想不明白為什麼這麼多人理解錯了,就是:用#include進來的檔案和本檔案不算兩個檔案,因為include預處理的時候就把程式碼直接加進來了,所以還是一個檔案,即使你在一個檔案裡申明一個變數前加了static(見下面詳細說明),然後用include包含進來,在本檔案也是可以用的!我所說的extern可以使變數在不同檔案共享,兩者沒有什麼包含關係,是獨立的,可以共用變數是靠編譯器連結功能實現的。繼續,當然,不是所有的全域性都要extern修飾,函式申明的時候自動是extern的,這點也要注意。

三、static關鍵詞

      這個關鍵詞是靜態的意思,顧名思義,其實這根extern感覺就是水火兩重天了,它修飾變數只能在本檔案可用,而且是靜態的,不會因為作用域的結束而消亡(但是隻能在作用域內用哈~,也就是static不改變變數的作用域)。這就帶來了些好處,如果兩個檔案用了相同的變數名的變數或者函式名一樣的函式,只要加了static就不會衝突;區域性變數加了static還有個常用的功能就是函式呼叫次數的計數。關於static我在另一篇文章中也提到了,可以看看:用GCC輸出帶原始碼的彙編程式進行連結的除錯

     最後,extern和static變數都是放在2、3所表示的區域,兩者還有個區別就是static你只能申明一次,為什麼?很顯然,因為由它修飾的變數只能在本檔案使用,故你如果申明時不初始化它自己會初始化自己為0,所以通常申明static時很多時候沒有認為初始化。可能還有人認為我說漏了auto和regester兩個修飾詞,這兩個通常有編譯器自動識別,編譯器至少這這一方面乾的比你出色~