首先幾個基本概念(網上的各類說法都很亂;我的理解整理了一下程序員
內存分類方法不少,動態、靜態; 五區; 三段;函數
內存的區:spa
1.動態存儲區分爲 棧區、堆區 也統稱爲堆棧段
1.1棧區(stack) 編譯器自動分配釋放,存放函數的參數值,局部變量的值等。函數結束自動釋放
1.2堆區(heap) 通常由程序員分配釋放, 若程序員不釋放,程序結束時可能由os回收。
new或者malloc出來的對象;(不釋放致使內存泄漏).net
2.靜態區域分爲 數據段(放數據)、代碼段(只讀)對象
2.1 全局區(數據段)—全局變量 和 靜態變量 的存儲 都是放在 數據段,
初始化的全局變量和靜態變量在一塊區域,
未初始化的全局變量和未初始化的靜態變量在相鄰的另外一塊區域。
程序結束後有系統釋放。blog
內存在程序編譯的時候就已經分配好,這塊內存在程序的整個運行期間都存在生命週期
2.2 文字常量區(代碼段) —常量字符串就是放在這裏的。 程序結束後由系統釋放。
(常量不容許修改)
常量區在代碼段裏,不佔內存,靜態存儲區在內存中
2.3 程序代碼區(代碼段) —存放函數體的二進制代碼。常量區與代碼區都是 代碼段的內存
總結到這裏,有個疑惑待解答;與ram和rom的聯繫;是否能夠認爲堆、棧、全局區是存在ram作用域
代碼段是在E方中存儲。文字常量不佔內存,可是還會釋放,應該不是在寶貴的E方里存儲字符串
再反過頭來從變量的角度看分配:
先說一個概念
做用域:起做用的區域。分爲
一、 代碼塊:一個{}包括的區域,甚至能夠在一個if的{}下定義變量,但不經常使用。通常都是在函數開頭定義。
二、 文件做用域:一個.c文件 (由static限定的全局變量在此。#include指令包含的其餘文件也算同一個文件
連接屬性:一共有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
函數:用法與變量相同,都是在.h文件中extern出去。
原理上來說:從連接屬性上說,須要extern的變量在b.c中是沒有定義的。t變量雖然具備全局可見性
編譯器在編譯各個獨立的文件時是相互不透明的,可是編譯器並不知道,因此須要extern一下,告訴編譯器放行。
能夠正常產生obj;在link階段,可見範圍擴大到整個程序。(如定義屢次會報錯)
extern 將變量從none屬性變爲external ,多個文件對應同一個實體
static 將變量從變爲internal(內部)
函數中使用全局變量,extern是說明符
標識符:就是變量的名字
關鍵字:變量類型
extern
https://blog.csdn.net/heli007/article/details/50518604
在一些複雜的項目中,
比較習慣在全部的函數聲明前添加extern修飾,
以防止遺漏包含頭文件而致使的編譯錯誤。
statichttps://blog.csdn.net/a827415225/article/details/45023949加了static後表示該函數失去了全局可見性,只在該函數所在的文件做用域內可見\