首先幾個基本概念(網上的各種說法都很亂;個人理解整理了一下
記憶體分類方法很多,動態、靜態; 五區; 三段;
記憶體的區:
1.動態存盤區分為 堆疊區、堆區 也統稱為堆疊段
1.1堆疊區(.stack) 編譯器自動分配釋放,存放函式的引數值,區域變數的值等,函式結束自動釋放
1.2堆區(.heap) 一般由程式員分配釋放, 若程式員不釋放,程式結束時可能由os回收,
new或者malloc出來的物件;(不釋放導致記憶體泄漏)
2.靜態區域分為 資料段(放資料)、代碼段(只讀)
2.1 全域區(.data)—全域變數 和 靜態變數 的存盤 都是放在 資料段,
初始化的全域變數和靜態變數在一塊區域,
未初始化的全域變數和未初始化的靜態變數在相鄰的另一塊區域,
程式結束后有系統釋放,
記憶體在程式編譯的時候就已經分配好,這塊記憶體在程式的整個運行期間都存在
2.2 文字常量區(.text) —常量字串就是放在這里的, 程式結束后由系統釋放,
(常量不允許修改)
常量區在代碼段里,不占記憶體,靜態存盤區在記憶體中
2.3 程式代碼區(.text) —存放函式體的二進制代碼,常量區與代碼區都是 代碼段的
總結到這里,有個疑惑待解答;與ram和rom的聯系;是否可以認為堆、堆疊、全域區是存在ram
代碼段是在E方中存盤,文字常量不占記憶體,但是還會釋放,應該不是在寶貴的E方里存盤
再反過頭來從變數的角度看分配:
先說一個概念
作用域:起作用的區域,分為
1、 代碼塊:一個{}包括的區域,甚至可以在一個if的{}下定義變數,但不常用,一般都是在函式開頭定義,
2、 檔案作用域:一個.c檔案 (由static限定的全域變數在此,#include指令包含的其他檔案也算同一個檔案,
但是static的變數還是要放在.c檔案中,因為雖然會include進.h檔案,但是在編譯時
會在.h檔案中也創建一個static變數,互不可見,
檔案作用域是僅僅對一個檔案起作用
3、全域可見:定義的全域變數,注意:對于全域變數的賦值必須在函式之內,除了初始化可以在外面賦值
鏈接屬性:一共有3種:
-
none(無)
總是被當做單獨的個體,也就是說該識別符號的多個宣告被當作獨立不同的物體, -
internal(內部)
在同一個源檔案中的所有宣告中都指向同一個物體,但位于不同源檔案的多個宣告則分屬不同的物體, -
external(外部):
不論宣告多少次、位于幾個源檔案都表示同一個物體,
區域變數: 在動態存盤區,函式結束釋放(在堆疊區stack上)
若沒有初始化,它的初始值是垃圾
同名內層塊會對把外層的變數隱藏掉,不要這樣用
作用域:代碼塊(既 一個{}括起來的一段代碼;函式中使用一般放在最開頭
靜態區域變數:static 在靜態存盤區(資料段) 函式呼叫結束保留 下次呼叫維持上次的值
僅在創造時初始化一次,沒有初始化默為0,(最好初始化,更嚴謹)
釋放:main函式是整個程式的宣告周期,靜態變數在main 的return之后釋放
(static改變了生命周期;沒有改變作用域,僅僅是存盤區域由堆疊變為資料段)
全域變數: 在靜態存盤區(資料段) 創造和初始化一次 沒有初始化值默為0
只能定義一次,可以多次宣告和參考
具有全域可見性,但是參考時需要extern
靜態全域變數:static 在資料段 用于解決重名問題,該變數只在本檔案使用
(所以一般不放在頭檔案,直接源檔案)
(static只改變作用域;限定可見性為該.C檔案)
全域變數的跨檔案參考:
跨檔案參考,只討論全域變數和函式
extern 是只宣告不定義
普通全域變數直接參考編譯會報錯,要extern才能用
具體用法:
變數:在a.c中定義了全域變數 struct t,在a.h中extern struct t;
并在b.c中#include a.h 然后就可以在b.c中使用,(這是專案 中的用法)
在b.c中extern 也可以,規范用法還是在.h中extern
原理上將,其實就是在b.c中extern,告訴編譯器,這個變數在別的檔案中定義,link階段再檢查
函式:用法與變數相同,都是在.h檔案中extern出去,并include使用
規范用法都是在a.h中extern 并 在b.c中include
EXTERN :宏定義:待補充
原理上來講:從鏈接屬性上說,需要extern的變數在b.c中是沒有定義的,t變數雖然具有全域可見性
編譯器在編譯各個獨立的檔案時是相互不透明的,但是編譯器并不知道,所以需要extern一下,告訴編譯器放行,
可以正常產生obj(二進制指令流);在link階段,可見范圍擴大到整個程式,
(如果此時發現該變數定義多次會報錯),
(link階段的另一個錯誤:函式有定義,有呼叫,但全域宣告區分了大小寫,link階段會報錯
編譯結束生成.exe檔案
extern 將變數從none屬性變為external ,多個檔案對應同一個物體
static 將變數從變為internal(內部)
在一些復雜的專案中,
比較習慣在所有的函式宣告前添加extern修飾,
以防止遺漏包含頭檔案而導致的編譯錯誤,
識別符號:就是變數的名字
關鍵字:變數型別
以下為準

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/36461.html
標籤:其他
上一篇:標記語言 腳本語言 編譯型語言
下一篇:如果你熱愛編碼,就應該少寫代碼
