C和汇编----存储类别、链接和内存管理
0x01 存儲類別
1、作用域
一個C變量的作用域可以是塊作用域、函數(shù)作用域、函數(shù)原型作用域或文件作用域。
1.1 塊作用域:
塊是用一對花括號括起來的代碼區(qū)域。比如函數(shù)體就是一個塊。定義在塊中的變量具有塊作用域,塊作用域變量的可見范圍是從定義處到包含該定義的塊的末尾
1.2 函數(shù)作用域
僅用于goto語句的標(biāo)簽。一個標(biāo)簽首次出現(xiàn)在函數(shù)的內(nèi)層塊中,它的作用域也延伸至整個函數(shù)
1.3 函數(shù)原型作用域
用于函數(shù)原型中的形參名,作用范圍是從形參定義處到原型聲明結(jié)束。這意味著,編譯器在處理函數(shù)原型中的形參時只關(guān)心它的類型,而形參名通常無關(guān)緊要。
1.4文件作用域
變量的定義在函數(shù)外面,具有文件作用域,從它的定義處到該定義所在文件的末尾均可見。
2、鏈接
C變量有3種鏈接屬性:外部鏈接、內(nèi)部鏈接或無鏈接。具有塊作用域、函數(shù)作用域或函數(shù)原型作用域的變量都是無鏈接變量。這意味著這些變量屬于定義他們的塊、函數(shù)或原型私有。具有文件作用域的變量可以是外部鏈接或內(nèi)部鏈接。外部鏈接變量可以在多文件程序中使用,內(nèi)部鏈接變量只能在一個文件中使用。當(dāng)一個文件作用域變量用static修飾時就是內(nèi)部鏈接
3、存儲期
C有4種存儲期:靜態(tài)存儲期、線程存儲期、自動存儲期、動態(tài)分配存儲期
- 靜態(tài)存儲期:在程序的執(zhí)行期間一直存在,文件作用域具有靜態(tài)存儲期
- 線程存儲期:用于并發(fā)程序設(shè)計,程序執(zhí)行可被分為多個線程。從被聲明到線程結(jié)束一直存在
- 自動存儲期:塊作用域的變量通常都具有自動存儲期,當(dāng)程序進(jìn)入定義這些變量的塊時,為這些變量分配內(nèi)存,當(dāng)退出這個塊時,釋放剛才為變量分配的內(nèi)存
4、存儲類別說明符
- auto:表名變量是自動存儲期,只能用于塊作用域的變量聲明中。由于在塊中聲明的變量本身就具有自動存儲期,所以使用auto主要是為了明確表達(dá)要使用外部變量同名的局部變量的意圖。
- register 說明符也只用于塊作用域的變量,它把變量歸為寄存器存儲類別,請求最快速度訪問該變量。同時,還保護(hù)了該變量的地址不被獲取。
- static 說明符創(chuàng)建的對象具有靜態(tài)存儲期,載入程序時創(chuàng)建對象,當(dāng)程序結(jié)束時對象消失。如果static 用于文件作用域聲明,作用域受限于該文件。如果 static 用于塊作用域聲明,作用域則受限于該塊。
- extern 說明符表明聲明的變量定義在別處。如果包含 extern 的聲明具有文件作用域,則引用的變量必須具有外部鏈接。如果包含 extern 的聲明具有塊作用域,則引用的變量可能具有外部鏈接或內(nèi)部鏈接,這接取決于該變量的定義式聲明。
5、小結(jié)
0x02 存儲類別和函數(shù)
函數(shù)也有存儲類別,可以是外部函數(shù)(默認(rèn))或靜態(tài)函數(shù)。外部函數(shù)可以被其他文件的函數(shù)訪問,但是靜態(tài)函數(shù)只能用于其定義所在的文件。
double gamma(double); /* 該函數(shù)默認(rèn)為外部函數(shù) */ static double beta(int, int); extern double delta(double, int);在同一個程序中,其他文件中的函數(shù)可以調(diào)用gamma()和delta(),但是不能調(diào)用beta(),因為以static存儲類別說明符創(chuàng)建的函數(shù)屬于特定模塊私有。這樣做避免了名稱沖突的問題,由于beta()受限于它所在的文件,所以在其他文件中可以使用與之同名的函數(shù)。
通常的做法是:用 extern 關(guān)鍵字聲明定義在其他文件中的函數(shù)。這樣做是為了表明當(dāng)前文件中使用的函數(shù)被定義在別處。除非使用static關(guān)鍵字,否則一般函數(shù)聲明都默認(rèn)為extern。
在rand0.c文件里:
static unsigned long int next=1; unsigned int rand0(void) {next=next*1103515245+12345;return (unsigned int) (next / 65536 )%32768; }在r_drive0.c文件里
#include "stdio.h"extern unsigned int rand0(void);int main(void) {int count;for(count = 0;count<5;count++)printf("%d\n",rand0());return 0; }next是靜態(tài)內(nèi)部鏈接,存儲期在程序的執(zhí)行期間一直存在,作用域是rand0.c文件,其他就不可以訪問了。
unsigned int rand0(void)是外部函數(shù),其他文件可以調(diào)用,用 extern 關(guān)鍵字聲明定義rand0.c文件里
0x03 分配內(nèi)存 malloc()和free()
- malloc():接收一個參數(shù),是所需內(nèi)存的字節(jié)數(shù),返回動態(tài)分配內(nèi)存塊的首字節(jié)地址。如果 malloc()分配內(nèi)存失敗,將返回空指針。malloc會找到合適的空閑內(nèi)存塊,這樣的內(nèi)存是匿名的,malloc()函數(shù)可用于返回指向數(shù)組的指針、指向結(jié)構(gòu)的指針等,所以通常該函數(shù)的返回值會被強(qiáng)制轉(zhuǎn)換為匹配的類型
- free()函數(shù)的參數(shù)是之前malloc()返回的地址,該函數(shù)釋放之前malloc()分配的內(nèi)存,一些操作系統(tǒng)在程序結(jié)束時會自動釋放動態(tài)分配的內(nèi)存,但是有些系統(tǒng)不會。為保險起見,請使用free(),不要依賴操作系統(tǒng)來清理。
- malloc()和free()的原型都在stdlib.h頭文件中。
- 因為char表示1字節(jié),malloc()的返回類型通常被定義為指向char的指針。然而,從ANSI C標(biāo)準(zhǔn)開始,C使用一個新的類型:指向void的指針,把指向 void的指針賦給任意類型的指針完全不用考慮類型匹配的問題
上面的程序是動態(tài)分配數(shù)組
反匯編:
ptd=(double )malloc(maxsizeof(double));的反匯編是:
0040102F 8B 45 F8 mov eax,dword ptr [ebp-8] 00401032 C1 E0 03 shl eax,3 00401035 50 push eax 00401036 E8 95 00 00 00 call malloc (004010d0) 0040103B 83 C4 04 add esp,4 0040103E 89 45 FC mov dword ptr [ebp-4],eax先將max的值傳給eax,左移eax三位,相當(dāng)于eax乘以8,就是40,剛好是傳給malloc的參數(shù)值,然后壓棧,調(diào)用malloc函數(shù),再把eax存入dword ptr [ebp-4]中。
free(ptd);反匯編:
先把dword ptr [ebp-4]的值傳給eax,就是40,是malloc分配內(nèi)存的大小,eax入棧,調(diào)用free函數(shù),釋放這段內(nèi)存
總結(jié)
以上是生活随笔為你收集整理的C和汇编----存储类别、链接和内存管理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 远控免杀专题8---BackDoor-F
- 下一篇: 颐和园划船从哪个门进