連接屬性
(1)你們知道程序從源代碼到最終可執行程序,經歷的過程:編譯、連接。
(2)編譯階段就是把源代碼搞成.o目標文件,目標文件裏面有不少符號和代碼段、數據段、bss段等分段。符號就是編程中的變量名、函數名等。運行時變量名、函數名可以和相應的內存對應起來,靠符號來作連接的。
(3).o的目標文件連接生成最終可執行程序的時候,其實就是把符號和相對應的段給連接起來。
C語言中的符號有三種連接屬性:外鏈接屬性、內連接屬性、無鏈接屬性。
整個4G的內存分配。
1.代碼段&只讀數據段:
代碼段:是存放整個代碼(函數)。只讀數據段:在程序運行的時候只能讀數據,不能改數據好比const 關鍵字修飾的變量。
2.數據段和bss段:
數據段:初始化非零的全局變量和static修飾定義的非零的局部變量。
bss段:未被初始化的全局變量和static修飾未被初始化的變量。
3.文件映射區:
當一個進程打開文件時,就直接在內存中改變文件內容,就是把硬盤裏的文件複製了一份在內存中,修改完成後保存後就將內存中寫到硬盤裏去。
4.堆:用mocall申請內存。free釋放內存。若是沒有釋放,內存就泄露了,是程序員手工操做的。
5.棧:局部變量,隨取隨用。函數的調用也涉及到棧。
6.內核映射區:將操做系統的內核程序映射到該區域了。
二.關鍵字:
1.auto:跟局部變量的使用沒有區別。加不加無所謂。
2.static:兩種用法:這兩種用法徹底不一樣。頗有迷惑性。。。。重要。
(1)修飾局部變量,造成靜態的局部變量,他的內存分配在 數據段/bss,此時對比局部變量,他的內存分佈在棧上。(存儲 類不一樣就衍生出許多不一樣)這就和局部變量上有了本質差異。(做用域、連接屬性、生命週期)做用域都是代碼塊 { }
(2)修飾全局變量,造成靜態的全局變量,靜態全局變量和全局變量有什麼區別。他們的區別就在連接屬性上了。
靜態局部變量存儲類和全局變量相同,做用域是代碼段。而全局變量是整個文件。
靜態局部變量鏈接屬性是無鏈接。全局變量是外鏈接。
3.extern:
聲明做用。 在a.C中的定義的全局變量,想要在b.C中用。就要用extern聲明該全局變量。否則就會沒定義。
4.volatile:
易變的。有時候在程序中(isr中斷服務程序、共線程、硬件自動置位)會改變某個變量的值。可是編譯器會幫咱們優化程序。好比
a=1;
b=a;
c=b; //編譯器會幫你優化成 c=b=a=1;
不會逐一去賦值,cpu執行效率高了。可是編譯器並不知道,他是沒有這個意識的,因此要加volatile 關鍵字。編譯器就會知道不去優化。若是是下面的這樣代碼,就會出錯。
do
{
*p=1;
}
while(*p) //*p的值有可能會被改,可是若是沒加volatile關鍵字的時候,編譯器就會將其優化成while(1)死循環。
可是加了volatile關鍵字時,編譯器就不會將其優化成while(1),而是寫成這樣 while(*p)
5.restrict:只用來修飾指針。若是加了restrict關鍵字,該指針指向的內存空間只能由該指針修改別的指針沒法修改。
2、做用域
局部變量:
全局變量:
重名變量的掩蔽規則:
3、生命週期:
棧上的分配的變量:函數每調用一次都會建立一次,而後使用,最後在函數返回的時候消亡。